gpt4 book ai didi

c++ - 什么时候可以在初始化列表中省略外括号?

转载 作者:IT老高 更新时间:2023-10-28 13:58:25 30 4
gpt4 key购买 nike

我在VC2010编译下面的代码时出现错误C2078。

struct A
{
int foo;
double bar;
};

std::array<A, 2> a1 =
// error C2078: too many initializers
{
{0, 0.1},
{2, 3.4}
};

// OK
std::array<double, 2> a2 = {0.1, 2.3};

我发现 a1 的正确语法是

std::array<A, 2> a1 = 
{{
{0, 0.1},
{2, 3.4}
}};

问题是:为什么 a1 需要额外的大括号,而 a2 却不需要?

更新

这个问题似乎并不特定于 std::array。一些例子:

struct B
{
int foo[2];
};

// OK
B meow1 = {1,2};
B bark1 = {{1,2}};

struct C
{
struct
{
int a, b;
} foo;
};

// OK
C meow2 = {1,2};
C bark2 = {{1,2}};

struct D
{
struct
{
int a, b;
} foo[2];
};

D meow3 = {{1,2},{3,4}}; // error C2078: too many initializers
D bark3 = {{{1,2},{3,4}}};

我仍然不明白为什么 struct D 给出错误但 B 和 C 没有。

最佳答案

需要额外的大括号,因为 std::array与标准库中的其他容器不同,它是一个聚合和 POD。 std::array没有用户定义的构造函数。它的第一个数据成员是一个大小为 N 的数组。 (您将其作为模板参数传递),并且此成员直接使用初始化程序初始化。直接初始化的 internal 数组需要额外的大括号。

情况同:

//define this aggregate - no user-defined constructor
struct Aarray
{
A data[2]; //data is an internal array
};

你会如何初始化它?如果你这样做:

Aarray a1 =
{
{0, 0.1},
{2, 3.4}
};

它给出了 compilation error :

error: too many initializers for 'Aarray'

这是您在 std::array 的情况下遇到的 相同 错误(如果您使用 GCC)。

所以正确的做法是如下使用大括号:

Aarray a1 =
{
{ //<--this tells the compiler that initialization of `data` starts

{ //<-- initialization of `data[0]` starts

0, 0.1

}, //<-- initialization of `data[0]` ends

{2, 3.4} //initialization of data[1] starts and ends, as above

} //<--this tells the compiler that initialization of `data` ends
};

其中compiles fine .再一次,需要额外的大括号,因为您正在初始化 internal 数组。

--

现在的问题是为什么在 double 的情况下不需要额外的大括号? ?

是因为 double不是聚合,而 A是。换句话说, std::array<double, 2>是聚合的聚合,而 std::array<A, 2>是聚合 1的聚合。

1.我认为在 double 的情况下仍然需要额外的大括号(如 this ),以完全符合标准,但代码在没有它们的情况下工作。看来我需要再次挖掘规范!

关于大括号和额外大括号的更多信息

我仔细研究了规范。本节(C++11 中的第 8.5.1/11 节)很有趣,适用于这种情况:

In a declaration of the form

T x = { a };

braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member. [ Example:

float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early and therefore y[3]s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0. In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,

float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. Likewise the next three are taken successively for y[1] and y[2]. —end example ]

根据我对上述引用的理解,我可以说应该允许以下内容:

//OKAY. Braces are completely elided for the inner-aggregate
std::array<A, 2> X =
{
0, 0.1,
2, 3.4
};

//OKAY. Completely-braced initialization
std::array<A, 2> Y =
{{
{0, 0.1},
{2, 3.4}
}};

在第一个中,内部聚合的大括号被完全省略,而第二个具有完全大括号的初始化。在您的情况下(double 的情况),初始化使用第一种方法(对于内部聚合,大括号完全省略)。

但这应该是不允许的:

//ILL-FORMED : neither braces-elided, nor fully-braced
std::array<A, 2> Z =
{
{0, 0.1},
{2, 3.4}
};

它既不是大括号省略,也没有足够的大括号来进行完全大括号初始化。因此,它是病态的。

关于c++ - 什么时候可以在初始化列表中省略外括号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11734861/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com