CppCoreGuidelines P.5 编译时检查比运行时检查好
22 December 2021
P.5 Prefer compile-time checking to run-time checking
理由
能在编译时检查出错误,就不要在运行时检查,这样可以不用编写错误处理代码。代码的可读性会更好、性能会更佳。
例子
以下代码在运行时检查 int
类型的长度是不是小于 32 位:
int bits = 0; // don't: avoidable code for (int i = 1; i; i <<= 1) ++bits; if (bits < 32) cout << "int too small\n"; cout << bits;
32
因为数值溢出的行为是未定义的,因此以上实现是不可靠的。可以用
static_assert
进行判断:
static_assert(sizeof(int) >= 4); // do: compile-time check
如果改成 >=8
静态判断就出错了:
static_assert(sizeof(int) >= 8); // do: compile-time check
C-src-99WMqo.cpp:11:27: error: static assertion failed 11 | static_assert(sizeof(int) >= 8); // do: compile-time check | ~~~~~~~~~~~~^~~~
更好的做法是使用int32_t
类型。
cout << sizeof(int32_t);
4
例子
如果传递给 read
函数的第二个参数过大的话,就会导致数组越界访问:
void read(int* p, int n); // read max n integers into *p int a[100]; read(a, 1000); // bad, off the end
如果使用了gsl::span
,编译器就能指导一次读取能放多少数据到数组了:
void read(gsl::span<int> r); // read into the range of integers r int a[100]; read(a); // better: let the compiler figure out the number of elements
其他
不要把能在编译时检查的动作延后到运行时。
强化
- 检查指针参数
- 检查运行时进行范围越界检测的代码