为什么仅在列表初始化时出现缩小转换警告?
Why does a narrowing conversion warning appear only in case of list initialization?
我有以下代码:
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;
}
为什么只有在列表初始化使用的情况下才会出现缩小转换警告?
list initialization 自 C++11 以来引入,具有禁止内置类型之间隐式缩小转换的功能。同时,另外两个 "old-style" (C++98 起) 使用圆括号和等号的初始化形式如
int val = 42;
A a(val);
A a = val;
不要更改它们的行为以符合列表初始化,因为这可能会破坏大量遗留代码库。
根据标准,缩小转换在该上下文中是非法的。它们在其他情况下是合法的。 ("illegal",我的意思是让程序格式错误)。
该标准要求编译器在特定情况下(使程序格式错误)发出诊断。标准未定义编译器在发出诊断后执行的操作。
MSVC 选择停止编译。 Gcc 选择发出鼻音 假装程序有意义,并进行转换,然后继续编译。
就标准而言,警告和错误都是诊断。传统上,错误就是您所说的编译器停止编译之前的诊断。
另请注意,编译器可以随时发出诊断信息。
传统上,当您执行标准规定程序格式正确但编译器作者认为不明智的操作时会使用警告,而当标准检测到格式错误的程序时会出现错误,但大多数编译器并未严格执行。
警告背后的原因已由其他答案解释。
这是解决此问题的方法 warning/error。创建一个以 initializer_list 作为参数的构造函数。
A(std::initializer_list<int> l) : value(*(l.begin())) {
cout << "constructor taking initializer list called\n";
}
我有以下代码:
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;
}
为什么只有在列表初始化使用的情况下才会出现缩小转换警告?
list initialization 自 C++11 以来引入,具有禁止内置类型之间隐式缩小转换的功能。同时,另外两个 "old-style" (C++98 起) 使用圆括号和等号的初始化形式如
int val = 42;
A a(val);
A a = val;
不要更改它们的行为以符合列表初始化,因为这可能会破坏大量遗留代码库。
根据标准,缩小转换在该上下文中是非法的。它们在其他情况下是合法的。 ("illegal",我的意思是让程序格式错误)。
该标准要求编译器在特定情况下(使程序格式错误)发出诊断。标准未定义编译器在发出诊断后执行的操作。
MSVC 选择停止编译。 Gcc 选择发出鼻音 假装程序有意义,并进行转换,然后继续编译。
就标准而言,警告和错误都是诊断。传统上,错误就是您所说的编译器停止编译之前的诊断。
另请注意,编译器可以随时发出诊断信息。
传统上,当您执行标准规定程序格式正确但编译器作者认为不明智的操作时会使用警告,而当标准检测到格式错误的程序时会出现错误,但大多数编译器并未严格执行。
警告背后的原因已由其他答案解释。
这是解决此问题的方法 warning/error。创建一个以 initializer_list 作为参数的构造函数。
A(std::initializer_list<int> l) : value(*(l.begin())) {
cout << "constructor taking initializer list called\n";
}