初始化struct成员时可能出现的MSVC 2013错误

时间:2016-06-28 01:28:06

标签: c++ c++11 visual-c++ initializer-list

MSVC 2013抱怨以下代码,虽然它在g ++中按预期工作。这看起来像是MSVC中的错误吗?

#include <iostream>
using namespace std;

struct A
{
    double x = 0.0, y = 0.0;
};

int main()
{
    A a{ 1.0, 2.0 };
    return 0;
}

请注意,如下更改struct可解决此问题。

struct A
{
    double x, y;
};

错误消息是:

  

错误1错误C2440:'初始化':无法转换   'initializer-list'到'A'

1 个答案:

答案 0 :(得分:6)

实际上,Visual Studio是正确的。

您的课程不是聚合,因此不能在其上使用聚合初始化:

  

[C++11: 8.5.1/1]:聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),没有用于非静态数据的 brace-or-equal-initializers 成员(9.2),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3)。

           

[C++11: 8.5.1/15]:表单中出现的初始化

T x(a);
T x{a};
     

以及new表达式(5.3.4),static_cast表达式(5.2.9),功能表示法类型转换(5.2.3)以及基本和成员初始值设定项(12.6.2) )被称为直接初始化

           

[C++11: 8.5.1/16]:初始值设定项的语义如下。 目标类型是要初始化的对象或引用的类型,源类型是初始化表达式的类型。当初始化程序是 braced-init-list 时,或者它是带括号的表达式列表时,未定义源类型。

     
      
  • 如果初始化程序是 braced-init-list ,则该对象 list-initialized (8.5.4)。
  •   
  • [...]
  •   

我不会引用它,但是[C++11: 8.5.4/3],其中 list-initialization 被定义,是我们的故事结束的地方。它显示没有初始化列表构造函数,并且假定您的列表有两个元素(不是一个而不是零),那么您的程序就是格式错误。

GCC实际上接受你的程序(example感谢Igor),虽然clang错误地(example,同样的信用)。

  

如果你是对的,这对于简单的结构来说是一些可怕的消息,因为我倾向于在任何地方使用默认初始化:struct A { double x{}, y{}; };

是的,如果你希望你的C ++ 11类是聚合的话,是时候停止这样做了。 :)

C ++ 14实际上已从8.5.1/1删除了大括号或等号初始化限制,因此切换到更新的标准将使您获得所需的位置。