为什么仅在列表初始化的情况下才会出现缩小转换警告?

Ale*_*lex 16 c++ initialization narrowing c++11 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;
}
Run Code Online (Sandbox Code Playgroud)

为什么仅在列表初始化使用的情况下才会出现缩小转换警告?

son*_*yao 17

自C++ 11以来引入了列表初始化,其功能是禁止在内置类型之间隐式缩小转换.同时,另外两个"旧式"(自C++ 98)初始化形式使用括号和等号之类的

int val = 42;
A a(val);
A a = val;
Run Code Online (Sandbox Code Playgroud)

不要改变他们的行为以符合列表初始化,因为这可能会破坏大量的遗留代码库.

  • 是否有编译器标志一致地引入该禁令? (2认同)

Yak*_*ont 9

根据标准,在这种情况下缩小转换是非法的.在其他情况下,它们是合法的.(通过"非法",我的意思是使程序格式不正确).

该标准要求编译器在该特定情况下(使程序格式错误)发出诊断.发出诊断后编译器执行的操作标准保留未定义.

MSVC选择停止编译.Gcc选择发出鼻子恶魔假装程序有意义,并进行转换,并继续编译.

就标准而言,警告和错误都是诊断.传统上,错误就是编译器停止编译之前所谓的诊断.

另请注意,编译器可以随时发出诊断信息.

传统上,当您执行某些操作时,标准指令是一个格式良好的程序但编译器作者认为不明智,并且当标准检测到格式错误的程序时出现错误,但大多数编译器都没有严格执行.

  • 在C99添加#error指令之前,通过在查看任何源文本之前无条件地输出"This is a diagnostic",实现可以满足诊断的所有要求.标准更明确地定义了#error指令,但仍然使所有其他要求无用地模糊. (3认同)