我有以下代码:
class A
{
public:
A(const unsigned int val) : value(val) {}
unsigned int value;
};
int main()
{
int val = 42;
A a(val);
A b{val}; // <--- Warning in GCC, error in Microsoft Visual Studio 2015
return 0;
}
为什么仅在列表初始化使用的情况下才会出现缩小转换警告?
答案 0 :(得分:17)
list initialization是自C ++ 11以来引入的,其功能是禁止在内置类型之间隐式缩小转换。与此同时,另外两个&#34;旧式&#34; (从C ++ 98开始)初始化表单使用括号和等号
int val = 42;
A a(val);
A a = val;
不要改变他们的行为以符合列表初始化,因为这可能会破坏大量遗留代码库。
答案 1 :(得分:9)
根据标准,缩小转换在此上下文中是非法的。在其他情况下,它们是合法的。 (通过“非法”,我的意思是使程序格式不正确)。
该标准要求编译器在该特定情况下(使程序格式错误)发出诊断。发出诊断后编译器的作用是标准的未定义。
MSVC选择暂停编译。 Gcc选择发出鼻子恶魔假装程序有意义,并进行转换,并继续编译。
就标准而言,警告和错误都是诊断。传统上,错误就是编译器停止编译之前所谓的诊断。
另请注意,编译器可以随时发出诊断信息。
当您执行某些操作时,传统上使用警告,标准规定是一个格式良好的程序,但编译器作者认为不明智,并且当标准检测到格式错误的程序时出现错误,但大多数编译器都没有严格执行。
答案 2 :(得分:0)
其他答案已经解释了警告背后的原因。
这是解决此警告/错误的方法。创建一个以initializer_list为参数的构造函数。
A(std::initializer_list<int> l) : value(*(l.begin())) {
cout << "constructor taking initializer list called\n";
}