零碎语言知识:
零碎语言知识
- map中,通过 for(auto &[key, value] : map) 中取出来的key的值默认是const类型的
- .h会定义多次变量,而.cc只会定义一次,每个引用#include ".h" 的地方都会定义一次变量。
cpp
// a.h -> gflag 声明
DECLARE_uint32(global_val);
// a.cc -> gflag 定义
DEFINE_uint32(global_val, 5000, "uint val of global");
// 任一使用.cc
#include "a.h"
const auto global_val = FLAGS_global_val;
处理 global_val;
- 最容易出现问题指针存储方式:容器存储对象,map结构存储<key, 对象指针>,当容器变动(map的rehash,vector的扩容),导致对象重新分配内存存储,这样map结构中的对象指针将失效,从而引发coredump等严重问题
cpp
class A {public: string name; int val;};
vector<A> aVec;
aVec.emplace(A("a", 1));
map<string, A*> name2Val;
name2Val["a"] = &aVec[0];
// 若后续不断emplace_back元素,导致aVec扩容,此时 &aVec[0] 与 彼时的 &aVec[0] 已经不同
name2Val["a"]; // -> 导致coredump
// 推荐做法:
vector<unique_ptr<A>> aUVec;
aVec.emplace(make_unique<A>("a", 1));
name2Val["a"] = aVec[0].get();
// 后续即使emplace_back元素,导致aVec扩容,也只是unique_ptr的地址发生变化,而不是对象的地址发生变化
name2Val["a"]; // bingo
给一个对比图

- 访问DCS时,若是热KEY,可能会击穿DCS缓存。 1. 本地拥有LRU能力。(不治本) 2. 当前一键屏蔽,返回一个失败的值。
- static变量一定需要在类外定义一次
- unordered_set插入A类型对象,需要为A定义哈希函数和等号运算符,或者使用unique_ptr包裹后使用。
- 下面代码共进行了多少次拷贝?
cpp
string GetName() {
string name = "xxx";
return name;
}
auto x = GetName();
// 7.1 没有开启返回值优化,xxx会先拷贝到返回值临时对象,再从临时对象拷贝到x,共2次拷贝,拷贝的方式会根据c++版本的不同而不同。
// 7.2 开启返回值优化,xxx会直接拷贝到x处。
- 不能move对象
cpp
真正不能move的对象主要包括:
基本类型(移动=拷贝,无意义但可行)
包含const成员、引用、不可移动成员的对象
明确删除移动操作的类型
某些标准库类型(std::mutex, std::atomic, std::array等)
union包含非平凡类型(需要特殊处理)
在C++中,"不能move"通常意味着:
编译错误(移动操作被删除)
移动退化为拷贝(性能无提升)
运行时未定义行为(如果强制转换并移动)
- memset 破坏虚函数指针, (因为虚函数指针指向了虚函数表) memcmp 填充数据无法正确比较
- const _cast 转化,只用来适配接口,且接口必须不修改原值(属于接口设计问题)
- static_assert()用于做编译期间的断言,编译时报错
- switch case [[fallthrough]] 表明显示下沉处理
- 资源访问校验:当外部数据参与数组索引,内存申请大小,内存复制长度,指针偏移等操作时,必须对数据的大小进行严格校验
- 条件变量:使用条件变量wait方法时,必须外加条件判断,并在循环中等待,原因有2:
cpp
1 通知丢失:线程A notify之后,线程B将一直等待下去,没有处理这次notify。
2 虚假唤醒:即使没有notify,线程B也可能会被唤醒。
优化小TIP
- 全局变量 复制一份给局部变量有简单优化,若全局变量较远,cache不容易获取,可能开销高于局部变量。
- 函数模块内,代码块优化位置调整:多个return false的并行无关联分支,建议把"最容易 return false"的分支放在最前面,减少因其return false而导致其余return true分支的动作浪费
- 数据结构之间,使用依赖而不是继承,可以减少继承带来的拷贝开销
- 小的临时局部变量,尽量不使用堆内存,因为分配堆malloc是个线程安全,带锁的函数,高并发场景下容易降低程序效率
- 全局变量,简单结构复制一份,增加缓存命中率;复杂结构使用指针引用,减少指令调用
- 复杂结构体初始化,使用模板定义后, memcopy_s而不是逐项赋值
- 检视时,查看for的必要性,统计信息可能不需要使用for