C++ 初始化中的自赋值 从我的最后一个问题出发,让我们考虑以下新的例子: #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”在这里未初始化使用,因为它在复制构造函数中用于构造自身。它导致未初始化的变量'm',从而显示垃圾。为什么编译器在这里不警告“b”是未初始化使用的(而“int a=a”产生这样的警告)C++ 初始化中的自赋值 从我的最后一个问题出发,让我们考虑以下新的例子: #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; },c++,C++,“b”在这里未初始化使用,因为它在复制构造函数中用于构造自身。它导致未初始化的变量'm',从而显示垃圾。为什么编译器在这里不警告“b”是未初始化使用的(而“int a=a”产生这样的警告) 因为它是未定义的行为,编译器可能会或不会给出任何警告!在这种情况下,编译器不需要提供诊断(警告/错误) 您的代码调用未定义的行为,因为b(在=的右侧)是未初始化的(正如您自己所知)-读取其值会调用UB。这与。的情况基本相同,因为它是未定义的行为,编译器可能会也可能不会给出任何警告!在这种情况下,编译器不需要提
因为它是未定义的行为,编译器可能会或不会给出任何警告!在这种情况下,编译器不需要提供诊断(警告/错误)
您的代码调用未定义的行为,因为
b
(在=
的右侧)是未初始化的(正如您自己所知)-读取其值会调用UB。这与。的情况基本相同,因为它是未定义的行为,编译器可能会也可能不会给出任何警告!在这种情况下,编译器不需要提供诊断(警告/错误)
您的代码调用未定义的行为,因为
b
(在=
的右侧)是未初始化的(正如您自己所知)-读取其值会调用UB。这与@Nawaz所述的情况基本相同,@kcm1700警告不是编译器的要求
至于为什么这个标志-weffc++
似乎比-Wall-Wextra-pedantic更严格,请参见在线文档:
您可以从文档中看到:
以下是我们的。。。选项不受-Wall的影响
<> > WebFc++(C++和Objul-C++)警告Scott Meyers的“有效C++系列”违反以下风格指南
books:定义的复制构造函数和赋值运算符
具有动态分配内存的类。更喜欢初始化而不是
构造函数中的赋值。Have operator=返回对的引用
*这个。当必须返回对象时,不要尝试返回引用。区分前缀和后缀形式的增量和
减量运算符。切勿超载&、| |或、,。此选项也适用
启用Wnon虚拟Dor,这也是一个有效的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)
^
见和相关的:
对于您在注释中修改的示例,clang正确地检测了这两种情况,请参见:和
输出为:
main.cpp:27:12: warning: variable 'b' is uninitialized when used within its own initialization [-Wuninitialized]
B b = b;
~ ^
1 warning generated.
不同的编译器在检测此类问题方面具有不同的能力。正如@Nawaz所述,@kcm1700警告不是编译器的要求
至于为什么这个标志-weffc++
似乎比-Wall-Wextra-pedantic更严格,请参见在线文档:
您可以从文档中看到:
以下是我们的。。。选项不受-Wall的影响
<> > WebFc++(C++和Objul-C++)警告Scott Meyers的“有效C++系列”违反以下风格指南
books:定义的复制构造函数和赋值运算符
具有动态分配内存的类。更喜欢初始化而不是
构造函数中的赋值。Have operator=返回对的引用
*这个。当必须返回对象时,不要尝试返回引用。区分前缀和后缀形式的增量和
减量运算符。切勿超载&、| |或、,。此选项也适用
启用Wnon虚拟Dor,这也是一个有效的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)
^
见和相关的:
对于您在注释中修改的示例,clang正确地检测了这两种情况,请参见:和
输出为:
main.cpp:27:12: warning: variable 'b' is uninitialized when used within its own initialization [-Wuninitialized]
B b = b;
~ ^
1 warning generated.
不同的编译器在检测此类问题时会有不同的能力。-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;
}
#包括
B类
{
公众:
B():m(17)
{
std::cout-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;
}
#包括
B类
{
公众:
B():m(17)
{
std::cout您使用的是什么编译器/平台/操作系统,大多数编译器都有会引发这种错误的标志warning@EdChum他的实时示例显示了带有-Wall
和-Wextra
的g++4.8并没有对此发出警告。@JBL添加-Weffc++
标志将生成:main.cpp:6:5:警告:“B::m”应该在成员初始值中初始化自定义列表[-Weffc++]
请参见编译器不负责报告所有情况下的警告,甚至不可能。编译器只是尽力检测这些情况。您使用的是什么编译器/平台/操作系统,大多数编译器都有会引发此类警告的标志warning@EdChum他的实时示例显示了带有-Wall
和-Wextra
doe的g++4.8sn不对此发出警告。@JBL添加-Weffc++
标志将生成:main.cpp:6:5:警告:“B::m”应在成员初始化列表[-Weffc++]中初始化
参见编译器不负责报告所有情况下的警告,这甚至是不可能的。编译器只是尽力检测这些情况。当然,编译器不需要报告所有情况下的警告