17

我有以下代码:

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;
}

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

4

3 回答 3

18

自 C++11 以来引入了列表初始化,具有禁止内置类型之间的隐式缩小转换的功能。同时,另外两种使用括号和等号的“旧式”(C++98 起)初始化形式,如

int val = 42;
A a(val);
A a = val;

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

于 2016-12-25T14:06:10.680 回答
9

根据该标准,在这种情况下,缩小转换是非法的。它们在其他情况下是合法的。(通过“非法”,我的意思是使程序格式错误)。

该标准要求编译器在该特定情况下发出诊断(使程序格式错误)。编译器在发出标准未定义的诊断后会做什么。

MSVC 选择停止编译。gcc 选择发出鼻恶魔假装程序有意义,然后进行转换,然后继续编译。

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

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

传统上,当您执行标准规定是格式良好的程序但编译器作者认为不正确时会使用警告,并在标准检测到格式错误的程序时使用错误,但大多数编译器并未严格执行。

于 2016-12-25T14:16:36.680 回答
0

其他答案已经解释了警告背后的原因。

这是解决此警告/错误的方法。创建一个以 initializer_list 作为参数的构造函数。

A(std::initializer_list<int> l) : value(*(l.begin())) { 
    cout << "constructor taking initializer list called\n";
}
于 2016-12-25T14:44:56.993 回答