C++ 核心准则边译边学 哲学篇.9: Don’t waste time or space 不要浪费时间和空间

源网址:CppCoreGuidelines

原因

因为这是C++!

注意

为了实现目标(例如开发速度,资源安全或者简化测试)花费的时间和空间不算浪费。“追求效率的另一个好处是,这个过程会迫使你更深入地理解问题。” -Alex Stepanov(PS:STL之父)

反例

struct X {
    char ch;
    int i;
    string s;
    char ch2;

    X& operator=(const X& a);
    X(const X&);
};

X waste(const char* p)
{
    if (!p) throw Nullptr_error{};
    int n = strlen(p);
    auto buf = new char[n];
    if (!buf) throw Allocation_error{};
    for (int i = 0; i < n; ++i) buf[i] = p[i];
    // ... manipulate buffer ...
    X x;
    x.ch = 'a';
    x.s = string(n);    // give x.s space for *p
    for (gsl::index i = 0; i < x.s.size(); ++i) x.s[i] = buf[i];  // copy buf into x.s
    delete[] buf;
    return x;
}

void driver()
{
    X x = waste("Typical argument");
    // ...
}

这是在讽刺,但是这些甚至更糟糕的错误我们都在工程代码中看到过。注意X的设计至少浪费了6字节(甚至更多)的空间。复制操作的虚假定义禁止了移动语义所以返回操作很慢(请注意这里不保证返回值优化RVO)。对bufnewdelete是多余的;如果我们确实需要一个局部的字符串,应该用string。还有几个性能bug和不必要的并发问题。

反例

void lower(zstring s)
{
    for (int i = 0; i < strlen(s); ++i) s[i] = tolower(s[i]);
}

这是来自生产代码中的实例。我们可以看到在我们的条件下有i < strlen(s)。这个表达式将在循环的每次迭代中进行评估,这意味着strlen必须在每次循环时遍历字符串来计算长度。当字符串内容变化时,假定toLower不会影响字符串长度,所以最好在循环外缓存长度避免每次迭代时的耗时。

注意

浪费的个例通常不重要,而且重要的地方通常可以被专家迅速消除。然而,在代码库中时空消耗的随意传播很容易变得影响重大,而且专家并不总是像我们想得那样有空。该规则(以及支持它的更具体的规则)的目的是在使用时将大多数C++相关的浪费消除在发生问题前。之后,我们可以查找与算法和需求相关的浪费,但这超出了这些准则的范围。

补充

许多更具体的规则旨在实现简化和消除非必要浪费的总体目标。

  • 注意来自用户定义的非默认后缀 operator++ 或 operator-- 函数的未使用返回值。优先使用前缀形式。 (注意:“用户定义的非默认”旨在限制范围。如果在实践中仍然实例很多,请回顾此条。)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值