C++ C++;从自参考字段检测初始化的警告

C++ C++;从自参考字段检测初始化的警告,c++,c++11,gcc,compiler-warnings,C++,C++11,Gcc,Compiler Warnings,我有一个错误,它是由一个错误的复制构造函数引起的,该构造函数从自身初始化了它的字段: Foo(const Foo& rhs) : bar(bar) // error {} 显然,这应该是: Foo(const Foo& rhs) : bar(rhs.bar) {} 是否存在可能检测到此问题的编译器诊断?这段代码可能有意义吗 -Winit self似乎没有意识到这一点 编辑 多亏了GCC4.9.2提供的警告,我更深入地了解了为什么我没有看到警告 事实证明,这取

我有一个错误,它是由一个错误的复制构造函数引起的,该构造函数从自身初始化了它的字段:

Foo(const Foo& rhs)
  : bar(bar)      // error
{}
显然,这应该是:

Foo(const Foo& rhs)
  : bar(rhs.bar)
{}
是否存在可能检测到此问题的编译器诊断?这段代码可能有意义吗

-Winit self
似乎没有意识到这一点

编辑

多亏了GCC4.9.2提供的警告,我更深入地了解了为什么我没有看到警告

事实证明,这取决于要复制的字段的类型

class A
{
public:
   A(const A&) : a(a), b(b), c(c) {}
private:
   int a;
   int* b;
   int& c;
};
此代码仅提供有关
a
(按值复制)和
b
(按指针复制)的警告,但不提供
c
(按引用复制)的警告

现在已经知道了这一点,期望GCC将来自self的引用的初始化确定为一个问题是否仍然合理

Clang确实将这三个都识别为警告,为
b

此处使用时,引用“b”尚未绑定到值

编辑我在GCC的bug追踪器中发现了一个问题:


现代编译器对此发出警告。例如,克朗说:

warning: field 'x' is uninitialized when used here [-Wuninitialized]
    Foo(Foo const & rhs) : x(x) {}
守则:

struct Foo
{
    Foo(Foo const & rhs) : x(x) {}
    int x;
};

现代编译器对此发出警告。例如,克朗说:

warning: field 'x' is uninitialized when used here [-Wuninitialized]
    Foo(Foo const & rhs) : x(x) {}
守则:

struct Foo
{
    Foo(Foo const & rhs) : x(x) {}
    int x;
};
在gcc中,可以使用flag
Winit self
(至少在gcc v 4.8.2标志上捕捉这种情况),或者干脆
Wall
。 在clang中,默认情况下通过flag
Wuninitialized
启用

在gcc 4.9.2上进行了试验。有警告。

在gcc中,您可以使用标志
Winit self
(至少在gcc v 4.8.2标志上捕捉这种情况),或者干脆
Wall
。 在clang中,默认情况下通过flag
Wuninitialized
启用


在gcc 4.9.2上进行了试验。有警告。

这在GCC中应该可以正常工作。检查编译器安装。使用
-Winit\u self

测试代码:

class Foo{
  int bar;
  public:
  Foo(const Foo& rhs)
   : bar(bar)      // error
  {}
};

int main()
{}
编译器输出:

main.cpp: In copy constructor 'Foo::Foo(const Foo&)':
main.cpp:4:3: warning: 'Foo::bar' is initialized with itself [-Winit-self]
   Foo(const Foo& rhs)
   ^
如果您使用的是Makefile,您可能需要检查它是否没有抑制任何警告

根据您的评论,在这种情况下,您最好能做出断言(并希望您做对):

#包括
使用名称空间std;
福班{
公众:
int&bar;
富(综合及工业)
:巴(一)
{}
Foo(施工Foo和rhs)
:巴(巴)
{
断言(&bar==&rhs.bar);
}
};
int main()
{
int i;
傅甲(i);;
富b(a),;
}

至少对我来说,这会导致断言失败。不幸的是,无法判断这是否是实现定义的。

这在GCC中应该可以正常工作。检查编译器安装。使用
-Winit\u self

测试代码:

class Foo{
  int bar;
  public:
  Foo(const Foo& rhs)
   : bar(bar)      // error
  {}
};

int main()
{}
编译器输出:

main.cpp: In copy constructor 'Foo::Foo(const Foo&)':
main.cpp:4:3: warning: 'Foo::bar' is initialized with itself [-Winit-self]
   Foo(const Foo& rhs)
   ^
如果您使用的是Makefile,您可能需要检查它是否没有抑制任何警告

根据您的评论,在这种情况下,您最好能做出断言(并希望您做对):

#包括
使用名称空间std;
福班{
公众:
int&bar;
富(综合及工业)
:巴(一)
{}
Foo(施工Foo和rhs)
:巴(巴)
{
断言(&bar==&rhs.bar);
}
};
int main()
{
int i;
傅甲(i);;
富b(a),;
}


至少对我来说,这会导致断言失败。很遗憾,无法判断这是否是定义的实现。

@bolov:仅在命名空间范围内。它们在其他作用域中也可以(只要第二个字符不是大写)。这种构造永远不会正确,因为您总是在读取未初始化或“尚未激活”的对象。@KerrekSB,在这种情况下,对这种情况进行编译器诊断有意义吗?@DrewNoakes:有,它们也有(参见我的答案).@bolov:仅在命名空间范围内。它们在其他作用域中也可以(只要第二个字符不是大写)。这种构造永远不会正确,因为您总是在读取未初始化或“尚未激活”的对象。@KerrekSB,在这种情况下,对这种情况进行编译器诊断有意义吗?@DrewNoakes:有,它们也有(参见我的答案)。在GCC中尝试了这一点(如问题中所述)。不起作用。gcc
4.9.1
-Wall-Wextra-Winit self-Wuninitialized
一起使用时,不显示任何警告。感谢提供示例。它触发了我做更多的测试,我确定这只发生在引用字段中(请参见编辑)。看起来这可能是GCC中的一个bug。在GCC中尝试过这个(如问题中所述)。不起作用。gcc
4.9.1
-Wall-Wextra-Winit self-Wuninitialized
一起使用时,不显示任何警告。感谢提供示例。它触发了我做更多的测试,我确定这只发生在引用字段中(请参见编辑)。看起来这可能是GCC中的一个错误。由于OP使用GCC编译,而且GCC似乎没有因为错误而对此发出警告,因此可能是使用clang编译不是一个(最佳解决方案)。从未使用过它,但怀疑在这种情况下是否可以使用clang static analyzer?结果是GCC 4.9.2在初始化参考字段时跳过了此警告。但是,它确实会对值和指针发出警告。由于OP是使用gcc编译的,而且由于存在错误,gcc似乎不会对此发出警告,因此使用clang编译可能不是一个(最佳解决方案)。从未使用过它,但怀疑在这种情况下是否可以使用clang static analyzer?结果是GCC 4.9.2在初始化参考字段时跳过了此警告。但是,它确实会对值和指针发出警告。请尝试将
字段设置为
int&
类型。我最初写问题的时候没有意识到这个要求。看编辑。哇,真讨厌。是的,可能是一个bug。你能做的最好的事情就是发布一个bug报告(你已经发布了),现在,使用断言在运行时捕获错误。请参阅我的编辑。要点是警告程序员(编译时)的错误。我看不出断言(运行时)在这里有什么帮助,除非它习惯于添加这个,我对此表示怀疑