初始化结构成员时可能出现 MSVC 2013 错误
Possible MSVC 2013 bug when initializing struct members
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;
};
错误信息是:
Error 1 error C2440: 'initializing' : cannot convert from
'initializer-list' to 'A'
实际上,Visual Studio是正确的。
您的 class 不是聚合,因此可能无法对其使用聚合初始化:
[C++11: 8.5.1/1]:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
[C++11: 8.5.1/15]:
The initialization that occurs in the forms
T x(a);
T x{a};
as well as in new
expressions (5.3.4), static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.
[C++11: 8.5.1/16]:
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression. The source type is not defined when the initializer is a braced-init-list or when it is a parenthesized list of expressions.
- If the initializer is a braced-init-list, the object is list-initialized (8.5.4).
- [...]
我不会全部引用,但是 [C++11: 8.5.4/3]
,其中 list-initialization 被定义,我们的故事就此结束。它表明如果没有初始化列表构造函数,并且假设您的列表有两个元素(不是一个也不是零),您的程序是错误的。
GCC 实际上不 接受您的程序(example thanks to Igor), though clang erroneously does (example,同样的信用)。
If you are right, these are some terrible news for simple structures because I tend to use default initialization everywhere: struct A { double x{}, y{}; };
是的,是时候停止这样做了,如果你想让你的 C++11 classes 成为聚合。 :)
C++14 实际上从 8.5.1/1
中删除了 brace-or-equal-initializers 限制,因此切换到更新的标准将使您到达想要的位置是。
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;
};
错误信息是:
Error 1 error C2440: 'initializing' : cannot convert from 'initializer-list' to 'A'
实际上,Visual Studio是正确的。
您的 class 不是聚合,因此可能无法对其使用聚合初始化:
[C++11: 8.5.1/1]:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal-initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
[C++11: 8.5.1/15]:
The initialization that occurs in the formsT x(a); T x{a};
as well as in
new
expressions (5.3.4),static_cast
expressions (5.2.9), functional notation type conversions (5.2.3), and base and member initializers (12.6.2) is called direct-initialization.
[C++11: 8.5.1/16]:
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression. The source type is not defined when the initializer is a braced-init-list or when it is a parenthesized list of expressions.
- If the initializer is a braced-init-list, the object is list-initialized (8.5.4).
- [...]
我不会全部引用,但是 [C++11: 8.5.4/3]
,其中 list-initialization 被定义,我们的故事就此结束。它表明如果没有初始化列表构造函数,并且假设您的列表有两个元素(不是一个也不是零),您的程序是错误的。
GCC 实际上不 接受您的程序(example thanks to Igor), though clang erroneously does (example,同样的信用)。
If you are right, these are some terrible news for simple structures because I tend to use default initialization everywhere:
struct A { double x{}, y{}; };
是的,是时候停止这样做了,如果你想让你的 C++11 classes 成为聚合。 :)
C++14 实际上从 8.5.1/1
中删除了 brace-or-equal-initializers 限制,因此切换到更新的标准将使您到达想要的位置是。