Skip to main content
  1. Docs/

一些 c++ 规范

·2 mins· ·
Cpp Cpp
Owl Dawn
Author
Owl Dawn
Table of Contents

cpp 规范
#

尽量不要使用全局变量
#

编译器很难对全局做优化。可以将全局变量打包在一起,做成 Context 对象,全文传递

如果一定要用全局变量,使用 static 修饰
#

使用 static 后,编译器确定变量不会被其他编译单元访问,可以做很多静态分析

使用 c++17 std::string_view 替换 std::string
#

cpp17 引入 string_view 来优化 std::string 的性能。它本身不 own 内存,只维护了一个指针和长度。其本质是一个 const char* 指针,字符串常量的初始化建议使用 std::string_view

不要在头文件中定义容器对象
#

在容器中定义的对象会被创建出来,不管 cpp 里有没有用到。而且任何 include 该头文件所编译出来的 .o 文件中也会创建这些对象。即 链接出来的二进制中有很多份对象

有时希望在头文件中定义让代码更一致,如:

static const std::unordered_map<std::string, int> map = {{"asdf", 4}}

​ 这是一种低效的实现,所有 include 这个头文件的都会初始化该对象,在链接时,这些对象都会被链接进产物并做运行时初始化

​ 可以通过维护一个 def 文件来描述映射关系

#ifndef MAP
#defind MAP(x, y)
#endif
MAP(asdf, 4)
...
#undef MAP

在需要该对象的地方,加上:

const std::unordered_map<std::string, int> map = {
#define MAP(x, y) {#x, y},
#include "xxx.def"
}

多用 std::array 而不是 std::vector
#

array 是分配在 栈 上,vector 分配在 堆 上,如果分配在堆上,分配和释放速度慢,且堆操作为动态,编译器优化是静态,无法知道内存情况,很难做优化

尽量避免指针的转换
#

int foo(short* s, int* i) {
    *i = 1;
    *s = 2;
    return *i;
}

int main() {
    int x = 0;
    x = foo((short*)&x, &x);
    std::cout >> x;
}

// g++ a.cpp  输出 2
// g++ a.cpp -O2  输出 1

对 cast 完的指针做 deference 是 undefined behavior,编译器可能会对其做优化。编译器提供选项 -fno-strict-aliasing 来禁掉该优化,但是关掉 strict-aliasing 对程序性能有巨大影响

  • strict-aliasing

    编译器在做别名分析(aliasing analysis)时,需要知道两个指针所指向内存是否存在交叉。该信息决定了指令之间的依赖关系,以及一块内存是否重新 load

    如:

    int a = *p;
    

慎用异常
#

异常被设计出来应该是做极端情况的容错处理的,不应该用来处理代码逻辑

  • 对于不抛出异常的逻辑,为零开销
  • 如果抛出异常,运行库会做两次调用栈回溯,过程非常耗费时间

x86 架构的一场实现本身不会对正常路径的程序性能有太多影响,但是会要求编译器在 eh_frame 中生成一些数据,会影响代码的 size,同时由于会插入很多代码处理异常发生情况,所以会影响 icache。如果确定代码中不会有异常,可以通过 -fno-exceptions 关掉

性能优化方法
#

cache 优化
#

写对性能友好的代码。相较于 CPU 的运算速度,内存访问耗时相当严重

如 遍历二维数组注意循环中元素的读取顺序

CPU 优化
#

  • 避免拷贝

    使用 emplace 簇函数

    定义移动构造函数和移动复制函数

    确认安全的前提下,使用 std::string_view 替代 std::string

函数签名
#

函数名 + 参数个数 + 参数类型 + 参数顺序 + const cv

const_iterator 和 iterator
#

  • 尽量使用 const_iterator 而不是 iterator

Related

Cgroup
·4 mins
Cgroup Cgroup
Cgroup v1 和 v2 的区别
·1 min
Cgroup Cgroup
LevelDB
·13 mins
linux 文件系统
·12 mins
redis
·19 mins
分布性一致算法
·10 mins