从上一个问题Initialisation of static variable with itself开始,让我们考虑一下新的例子:
#include <iostream>
class B
{
public:
B()
{
std::cout << "B()" << std::endl;
m = 17;
}
B(const B & o)
{
std::cout << "B(const B& o)" << std::endl;
m = o.m;
}
B & operator=(const B & o)
{
std::cout << "B & operator=(const B & o)" << std::endl;
m = o.m;
return *this;
}
int m;
};
int main()
{
B b = b;
std::cout << b.m << std::endl;
}
程序的输出是
B(const B& o)
1840828080
'b'在这里使用未初始化,因为它在复制构造函数中用于构造自身。它导致未初始化的变量'm',从而显示垃圾。为什么编译器不会在这里发出警告,'b'是未初始化的(而'int a = a'会产生这样的警告)。
答案 0 :(得分:3)
因为它是未定义的行为,编译器可能会也可能不会发出任何警告!在这种情况下,编译器不要求提供诊断(警告/错误)。
并且您的代码调用未定义的行为,因为b
(在=
的右侧)未初始化(如您所知) - 读取其值会调用UB。它基本上与this one相同。
答案 1 :(得分:1)
-Weffc ++绝对不是答案!警告只是说,初始化应该进入初始化列表。如果你这样做,警告就会消失:
#include <iostream>
class B
{
public:
B() : m(17)
{
std::cout << "B()" << std::endl;
}
B(const B & o) : m(o.m)
{
std::cout << "B(const B& o)" << std::endl;
}
B & operator=(const B & o)
{
std::cout << "B & operator=(const B & o)" << std::endl;
m = o.m;
return *this;
}
int m;
};
int main()
{
B b = b;
int i = i;
std::cout << b.m << " " << i << std::endl;
}
live example处的编译器给出了简单变量i的警告,但没有给出类变量b的警告。 所以这个问题仍然没有答案 - 为什么编译器会警告一个简单的类型,而不是一个更复杂的类型呢?
答案 2 :(得分:0)
正如@Nawaz所述,@ kcm1700警告不是编译器的要求。
至于为什么此标记-weffc++
似乎比-Wall -Wextra -pedantic
更严格,请参阅在线文档:http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html。
您可以从文档中看到:
以下-W ...选项不受-Wall的影响。
-Weffc ++(仅限C ++和Objective-C ++)警告Scott Meyers&#39;以及违反以下风格指南的行为?有效的C ++系列 书籍:定义复制构造函数和赋值运算符 具有动态分配内存的类。首选初始化 在构造函数中的赋值。有operator =返回引用 *这个。必须返回对象时,不要尝试返回引用。区分增量和前缀和后缀形式 减少运营商。永远不要过载&amp;&amp;,||,或。这个选项也 启用-Wnon-virtual-dtor,它也是有效的C ++之一 建议。然而,检查延长以警告缺乏 可访问的非多态基类中的虚析构函数。
选择此选项时,请注意标准库标题 不遵守所有这些准则;使用'grep -v'来过滤掉那些 警告。
因此,如果您添加-weffc++
标志,那么它将生成所需的警告:
g++-4.8 -std=c++11 -Weffc++ -Wall -Wextra -pedantic main.cpp && ./a.out
main.cpp: In constructor 'B::B()':
main.cpp:6:5: warning: 'B::m' should be initialized in the member initialization list [-Weffc++]
B()
^
main.cpp: In copy constructor 'B::B(const B&)':
main.cpp:12:5: warning: 'B::m' should be initialized in the member initialization list [-Weffc++]
B(const B & o)
^
请参阅live example及相关信息:Easy way find uninitialized member variables
对于评论中的修改后的示例,clang会正确检测到这两个示例,请参阅:http://coliru.stacked-crooked.com/a/d1a55f347ee928be和http://coliru.stacked-crooked.com/a/9676797c7d155b81
输出结果为:
main.cpp:27:12: warning: variable 'b' is uninitialized when used within its own initialization [-Wuninitialized]
B b = b;
~ ^
1 warning generated.
不同的编译器在检测此类问题方面具有不同的能力。