CL.ASSIGN.NON_CONST_ARG
将非常量对象传递给赋值运算符 =
这是一个类级别 (CL) 检查器,可就赋值运算符的参数类型,告知您潜在的限制或不明智的设计选择。类级别检查器会根据 Scott Meyer 的高效 C++ 规则类构造来生成建议。
CL.ASSIGN.NON_CONST_ARG 检查器会查找将非常量对象传递给运算符 = 的类。使用这种代码时,将无法表达某些语言结构。无论这些语言结构是否需要,或是否具有争议,遵循下面的基本模板,以在无论使用何种类型时均能保证语言的一致性:
复制
class MyClass {
public:
MyClass& operator=(const MyClass&);
};
当赋值运算符返回时,它可返回 *this 或该运算符右侧的内容,例如:
复制
class C{
//...
public:
C& operator=(const C& rhs){
return rhs;
}
//...
};
显然,将常量属性从没有显式 const_cast 的 rhs 删除时,不会进行编译,无论如何,这不会是什么好主意。对于这种情况,一个可能的快速解决方案(最终表明是个糟糕的方法)是仅将 rhs 参数声明为一个非常量引用:
复制
class C{
//...
public:
C& operator=(C& rhs){
return rhs;
}
//...
};
现在,该代码将进行编译,但是此解决方案使您无法将编译器创建的临时对象分配给您的类。例如:
复制
class C{
//...
public:
C& operator=(C&);
C(int);
//...
};
//...
C obj = 10;
在本例中,编译器将为整数构建一个常量临时对象,然后尝试找到将该常量临时对象视作输入的赋值运算符。显然,此操作将失败,因为只存在非常量赋值运算符。再一次,最好的建议还是尽可能遵循适用于赋值运算符的简单标准模板。
漏洞与风险
此设计选择不存在任何漏洞,但是有风险,即不熟悉的程序员将尝试使用“应该”正常工作但是不兼容的语言结构,并且还会遇到意义甚少或毫无意义的编译器警告(假定 C++ 编译器输出具有通常的复杂性)。
漏洞代码示例
复制
class C{
//...
public:
C& operator=(C& rhs){
return rhs;
}
//...
};
在此示例中,Klocwork 在第 3 行查找到一个 CL.ASSIGN.NON_CONST_ARG 错误,该错误违反了类构建规则。
修正代码示例
复制
class C{
//...
public:
C& operator=(const C& rhs){
return *this;
}
//...
};
在该修正代码示例中,运算符 = 返回 *this 并避免了违反该规则。