☰
  • 首页
  • 规则分类
  • 项目介绍
search
•••

不应重载“逻辑与”和“逻辑或”运算符

6.8.10 ID_overloadLogicOperator
目录 › next › previous

重载“逻辑与”、“逻辑或”等运算符会影响效率,甚至会导致不符合预期的结果。

对于非重载的内置“逻辑与”、“逻辑或”运算符,标准要求从左到右依次对子表达式求值,一旦可以确定整个表达式的值,计算就会立即停止,如果还有其他子表达式未被求值,也不会再进行计算,这就是“短路规则”,其目的是为了提高效率。然而,运算符的重载会导致短路规则失效,甚至会导致逻辑错误。

示例:

struct A {
    A();
    bool valid() const;
    A& assign(const A&);
};

bool operator && (const A& x, const A& y) {  // Non-compliant
    return x.valid() && y.valid();
}

设 a 和 b 为 A 类对象:

b && a.assign(b)  // Logic error

按常理,此表达式的意思是如果 b 在某种意义上为真,就用 b 对 a 赋值,否则不进行赋值,但由于 && 被重载成了函数,左右子表达式成了函数的参数,短路规则不再有效。在 C++17 之前,所有参数的求值顺序均是未声明的,a.assign(b) 可能会先被执行,造成完全不符合预期的结果,C++17 明确了重载运算符参数的求值顺序与内置运算符一致,但仍然无法遵守短路规则,a.assign(b) 总会被执行。

解决方法:

struct A {
    explicit operator bool() const {
        return valid();
    }
    ....
};

去掉对 && 的重载,在类中定义 bool 类型转换运算符,既可保证求值顺序,又可遵守短路规则。

相关

ID_overloadComma

依据

ISO/IEC 14882:2003 5.2.2(8)-unspecified ISO/IEC 14882:2011 5.2.2(8) ISO/IEC 14882:2017 16.3.1.2(2)

参考

MISRA C++ 2008 5-2-11
Copyright©2024 360 Security Technology Inc., Licensed under the Apache-2.0 license.