C++ 核心准则边译边学 哲学篇.7:Catch run-time errors early 尽早捕获运行期错误

原因

避免“神秘的”崩溃,避免错误导致(可能无法识别的)错误结果。

例子

void increment1(int* p, int n)    // bad: error-prone
{
    for (int i = 0; i < n; ++i) ++p[i];
}

void use1(int m)
{
    const int n = 10;
    int a[n] = {};
    // ...
    increment1(a, m);   // maybe typo, maybe m <= n is supposed
                        // but assume that m == 20
    // ...
}

这里我们在use1中犯了一个可能导致损坏数据或者崩溃的小错误。(pointer,count)风格的接口导致increment1()没有一个实际的方法避免范围越界错误。如果我们可以检查超出范围的下标,那么将会在访问p[10]之前被发现。我们可以提前检查并优化代码:

void increment2(span<int> p)
{
    for (int& x : p) ++x;
}

void use2(int m)
{
    const int n = 10;
    int a[n] = {};
    // ...
    increment2({a, m});    // maybe typo, maybe m <= n is supposed
    // ...
}

现在,m <= n可以在指针调用前检查而不是之后。如果我们想用n作为边界但是拼写错误,代码可以进一步简化(消除错误的可能性):

void use3(int m)
{
    const int n = 10;
    int a[n] = {};
    // ...
    increment2(a);   // the number of elements of a need not be repeated
    // ...
}

反例

不要重复检查相同的值。不要以字符串传递结构化数据传递:

Date read_date(istream& is);    // read date from istream

Date extract_date(const string& s);    // extract date from string

void user1(const string& date)    // manipulate date
{
    auto d = extract_date(date);
    // ...
}

void user2()
{
    Date d = read_date(cin);
    // ...
    user1(d.to_string());
    // ...
}

日期被验证两次(通过Date结构体)并且通过字符串传递(非结构化的数据)。

例子

过度检查可能代价高昂。在某些情况下,早期检查效率低下,因为您可能永远不需要该值,或者可能只需要比整体更容易检查的部分值。类似的,不要增加改变接口渐近行为的有效性检查(例如,不能给一个平均复杂度O(1)的接口添加一个O(n)的检查)。

class Jet {    // Physics says: e * e < x * x + y * y + z * z
    float x;
    float y;
    float z;
    float e;
public:
    Jet(float x, float y, float z, float e)
        :x(x), y(y), z(z), e(e)
    {
        // Should I check here that the values are physically meaningful?
    }

    float m() const
    {
        // Should I handle the degenerate case here?
        return sqrt(x * x + y * y + z * z - e * e);
    }

    ???
};

由于可能的测量误差,jet的物理规律并不是不变的。

补充

  • 查看指针和数组:尽早进行范围检查而且不要重复检查
  • 查看转换:消除或者缩小窄化转换
  • 查找来自输入的未经检查的值
  • 查找结构化数据(对象或者不变的类)被转换为字符串
  • ???
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值