CppCoreGuidelines P.3 明确地表达程序意图
20 December 2021
如果要读代码注释才能理解代码意图,那可能就意味着代码写的不够清晰,代码意图没有明确地表达了。
例如,以下例子:
vector<int> v = {1, 2, 3, 4, 5}; gsl::index i = 0; while (i < v.size()) { cout << v[i] << " "; i++; }
1 2 3 4 5
这里,我们的意图其实就是要循环一遍 v
,把其元素的值打印出来。然而,别人可能无法一眼看出来代码要做的事情。并且,代码里还多余的定义了一个索引变量 i
,这个变量的有效范围还超出了循环体。
倘若把 while
循环改成以下 for
循环,就比较直截了当了:
vector<int> v = {1, 2, 3, 4, 5}; for (const auto& x : v) { cout << x << " "; }
1 2 3 4 5
并且,还用了 const
修饰 x
,表示循环内不会修改 x
的值。如果循环中修改了 x
的值,编译器会报错。
vector<int> v = {1, 2, 3, 4, 5}; for (const auto& x : v) { cout << ++x << " "; }
C-src-eO7Jst.cpp: In function 'int main()': C-src-eO7Jst.cpp:14:15: error: increment of read-only reference 'x' 14 | cout << ++x << " "; | ^
如果明确要在循环中修改 x
,那么可以去掉 const
:
vector<int> v = {1, 2, 3, 4, 5}; for (auto& x : v) { cout << ++x << " "; }
2 3 4 5 6
也可以用 std::ranges::for_each
更清晰的表达程序意图:
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; std::ranges::for_each(v, [](const auto &x) { cout << x << " "; });
1 2 3 4 5 6 7 8 9 0
需要注意的是,在 algorithm
中,也有一个 std::for_each
,它的前两个参数是 InputIterator
:
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; for_each(begin(v), end(v), [](int x) { cout << x << " "; });
1 2 3 4 5 6 7 8 9 0
如果,循环访问的时候,不用按顺序,可以添加 execute::par
表示并行访问。因为 v
的元素不够多,所以看不出什么变化:
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; for_each(execution::par, v.begin(), v.end(), [](int x) { cout << x << " "; });
1 2 3 4 5 6 7 8 9 0
如果要表示在两点间画线,以下两种写法里,第二种就比较明确:
draw_line(int, int, int, int); // obscure draw_line(Point, Point); // clearer
一些建议:
- 熟悉掌握指南支持的程序库(guidelines support library, gsl)
- 熟悉了解 ISO C++ 标准库
- 其他项目中使用的基础库
一些需要注意的地方:
- 简单的 for 循环 vs. 带范围的
for_each
f(T*, int)
接口 vs.f(span<T>)
接口- 循环变量超出循环体范围
- naked
new
anddelete
(没看懂……) - 有过多内置类型的函数参数