复制构造函数和赋值运算符定义不一致(“二法则”)¶
ID: cpp/rule-of-two
Kind: problem
Security severity:
Severity: warning
Precision: high
Tags:
- reliability
- readability
- language-features
Query suites:
- cpp-security-and-quality.qls
此规则查找定义了复制构造函数或复制赋值运算符,但未同时定义两者。编译器会为这些函数生成默认实现,由于它们处理的是类似的关注点,因此如果其中一个的默认实现不能令人满意,则另一个也可能不能令人满意。
当一个类定义了复制构造函数或复制赋值运算符,但未同时定义两者时,可能会导致意外的行为。对象初始化(即,Class c1 = c2
)的行为可能与对象赋值(即,c1 = c2
)的行为不同。
建议¶
首先,考虑用户定义的成员是否需要显式定义。如果类没有提供用户定义的复制构造函数,则编译器将始终尝试生成一个公共复制构造函数,该构造函数递归调用每个字段的复制构造函数。如果现有的用户定义的复制构造函数执行完全相同的操作,则最有可能是删除它。编译器生成的版本可能更高效,并且不需要随着字段的添加和删除而手动维护。
如果用户定义的成员 *确实* 需要存在,则应定义另一个对应的成员。如果编译器生成的实现可以接受,则可以使用 = default
将其定义为默认的,或者如果它不应该被调用,则可以使用 = delete
将其定义为删除的。
示例¶
class C {
private:
Other* other = NULL;
public:
C(const C& copyFrom) {
Other* newOther = new Other();
*newOther = copyFrom.other;
this->other = newOther;
}
//No operator=, by default will just copy the pointer other, will not create a new object
};
class D {
Other* other = NULL;
public:
D& operator=(D& rhs) {
Other* newOther = new Other();
*newOther = rhs.other;
this->other = newOther;
return *this;
}
//No copy constructor, will just copy the pointer other and not create a new object
};