类或者结构体常用数据前置
结构体数据不要嵌套太深,因为每一级的嵌套都意味着一次的寻址
相关的数据放到一起,提升数据的耦合性,提高访问效率
常用数据前置,以免导致页交换等
1 | struct compact{ |
几种构造函数
默认构造函数
初始化构造函数
拷贝构造函数
赋值构造函数
1 | struct MyData { |
1 | Default Construct |
类成员的初始化放到初始化列表中
1 | class MyType2 { |
内存相关的优化
尽量使用栈内存,少用堆内存
堆内存是new出来的,慢,且容易产生碎片
堆内存也更容易被操作系统给交换到外存中。- 引用传参
placement new
- new不能被重载,它先调用operator new分配内存,然后调用构造函数初始化那段内存
- operator new 要实现不同的内存分配行为,需要重载operator new, 而不是new
- placement new是operator new的一个重载版本,它不分配内存,只是返回只想已经分配好的某段内存的一个指针,因此不能删除它,只能调用对象的析构函数。placement new重用了已有的内存,没有频繁的内存申请和释放,提升了性能,减轻了碎片化。
1 | void testPlacementNew() { |
循环优化
++iter 相比于iter++ 会少一步指令
外小内大
二维数组是按行存储的。如果一行存储的数据超过了数据分页,那么按列访问就会导致频繁的跨页访问。
连续访问的数据比跳页访问要快
外小内大的方式还能节约内存,因为页面交换的时候可能需要额外的内存来帮助1
2
3
4
5
6
7
8void testSmallbig(){
double data[100][10000];
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 10000; j++) {
data[i][j] = i * j;
}
}
}
C++ 新特性的性能优化
右值引用和移动语义
减少两个对象交互时的不必要copy1
2
3
4
5
6
7
8
9void test() {
vector<int> vs;
vs.resize(100000);
for (auto v : s) {
v = v + 1;
}
vector<int> vs1 = vs;
vector<int> vs2 = std::move(vs);
}
使用前提:
- 定义的类使用了资源并定义了移动构造函数和移动赋值运算符
- 该变量即将不再使用
unordered_map
make_shared
1 | std::shared_ptr<Data> spw(new Data); |
final
constexpr
编译期计算
容器选择
vector > deque > list/forward_list
qsort比sort快
编译器优化
- 短小函数inline化
- PGO