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'
答案 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
删除了大括号或等号初始化限制,因此切换到更新的标准将使您获得所需的位置。