04 January 2022

C++ 核心指南目录

P.11: Encapsulate messy constructs, rather than spreading through the code

理由

代码散乱既难维护又容易隐藏 bug。尽量通过接口封装代码,好的接口易用有安全。

例子

int sz = 10;
int* p = (int*) malloc(sizeof(int) * sz);
int count = 0;
int input_max = 20;
int input_val = 0;
for (;;) {
    int x = input_val++;
    if (input_val > input_max) break;
    if (count == sz)
        p = (int*) realloc(p, sizeof(int) * sz * 2);
    p[count++] = x;
}
for (int i=0; i<count; i++) cout << p[i] << " ";
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

上面的代码进行底层内存操作、繁琐又容易出错。此处可以使用 vector

vector<int> v;
v.reserve(100);
int input_max = 20;
int input_val = 0;
for (;;) {
    int x = input_val++;
    if (input_val > input_max) break;
    v.push_back(x);
}
std::ranges::for_each(v, [](const auto &x){cout << x << " ";});
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

注意

标准库和 GSL 是符合本条原则指南的。比如,为了避免数组、联合体、类型转换等诡异的生命周期管理。gsl::owner等工具可以实现关键的抽象机制,比如 vector , span, lock_guard, future 等。我们应该使用那些由更专业的时间花费大量时间开发的程序库。同样的,我们应当设计实现更多专业的程序库给用户使用,而不是让他们(很多时候是我们自己)重复的处理底层代码。

强化

  • 检查“混乱的代码”,比如复杂的指针操作、抽象实现之外的类型转换。