考虑以下程序:
#include <string>
struct S {
S (){}
private:
void *ptr = nullptr;
std::string str = "";
};
int main(){}
当在GCC 4.7.1上使用-Weffc++
编译时,将显示:
警告:"struct S"具有指针数据成员[-Weffc++]警告:但不覆盖"S(const S&)"[-Weffc++]警告:或"operator=(const S&)"[-Weffc++]
这在正常情况下没有问题,除了以下几个例子:
如果我注释掉任何构造函数、指针声明或字符串声明,则警告将消失。这很奇怪,因为你可能认为只有指针就足够了,但事实并非如此。此外,将字符串声明更改为整数声明也会导致它消失,因此只有当有字符串(或可能是其他选择类)时才会出现。为什么在这种情况下警告会消失?
通常,当指针所做的一切都指向一个现有变量(通常由操作系统维护)时,就会出现此警告。没有
new
,也没有delete
。在这些情况下,当带有句柄的类被复制时,我不想要深度复制。我希望两个句柄都指向同一个内部对象(例如窗口)。有没有什么方法可以让编译器实现这一点,而不必重载复制构造函数和赋值运算符,或者用#pragma
完全禁用警告?当"三条规则"根本不适用时,为什么我一开始就感到烦恼?
GCC的-Weffc++
有几个问题,我从来没有使用过它。检查"问题"的代码非常简单,因此警告最终过于直率,毫无帮助。
这个特别的警告是基于有效C++第一版的第11项,Scott在后来的版本中对其进行了更改(为了更好)。G++代码不检查实际的动态分配,只检查指针成员的存在。
当比较第一版和第三版中的指南时,请参阅我在GCC的bugzilla中写的关于此警告的内容:
第11项:为具有动态分配的内存。
替换为第14项:"仔细考虑中的复制行为资源管理类"-建议不那么具体,但更有用但不知道如何将其转化为警告!
-
当你这样做的时候,你有一个POD结构。由于
-Weffc++
不能有任何构造函数,所以它不需要检查。 -
使用引用或
shared_ptr
对象或任何其他包裹指针的对象。
老问题但是"这在正常情况下是没有问题的"并非完全正确:
-Weffc++强制您的代码反映行为。这里要说的是,如果您按原样使用代码,则隐式复制运算符将只生成";ptr";指向与原始结构相同的地址。
也许这就是你想要的原因,但它只是警告你,因为这是一种隐含的行为。这对正在编写代码的您来说可能很清楚,但对其他开发人员来说会清楚吗?
要消除此警告,您应该显式删除copy和=运算符,或者定义它们。要删除复制构造函数,您可以执行以下操作:
S(const S&) = delete;