- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我在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]
, namelyy[0][0]
,y[0][1]
, andy[0][2]
. Likewise the next two lines initializey[1]
andy[2]
. The initializer ends early and thereforey[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 fory[1]
andy[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/
这是我在这里的第一篇文章,也是我第一次使用 C++。我正在查看从 Internet 获得的一些代码,但我对此有疑问。 它有一个 for 循环,像这样: for(cin >> t;t--;) 我明白它在
我目前正在开发一个网站,除其他外,该网站允许用户通过显示或隐藏他们已购买的商品来过滤市场。这适用于基本的 AJAX 调用,该调用传递可用过滤器的当前条件,然后使用 CodeIgniter 的事件记录构
我创建了一个 MWE,其中通过添加 来更改单行解决编译器错误。 以下代码无法编译: import java.util.List; public class MainClass { publi
当我想测试一些 PostgreSQL 函数 FOO() 的行为时,我发现执行类似 SELECT FOO(bar) 的查询很有用,bar一些数据我用作直接输入,而无需从真实表中SELECT。 我读到我们
在 PHP、Java、C++(以及许多其他语言)中,for 循环是这样使用的: for(int i=0;i<10;i++) 如果我已经初始化了i,我该如何省略初始化语句呢? 最佳答案 在 Java、C
我发现我们的 Android 应用出现了一个奇怪的问题,特别是在 4.4 版的 Moto X 上。 在偏好 Activity 中,所有标题的前 8 个字符都在开头用省略号截断。这也发生在溢出菜单和整个
我有一个 XElement,我必须解析它以删除结束标记中的空白。我的代码如下所示: var stringBuilder = new StringBuilder(); using (var string
假设我有两个接口(interface),X和 Y ,它们共享一些字段,但也有独立的字段: interface X { abc: number; foo: number; bar: numb
我有这个模型: var accountSchema = new mongoose.Schema({ 'seeker': { 'fullName': String,
我在 R 中运行一个具有大量时间和位置固定效应的回归。我尝试将一个漂亮的汇总表输出到 Latex 中。我从 stargazer 包切换到 huxtable,因为 stargazer 在忽略固定效果时表
假设我有一个数据框: a df a b c d 1 0 9 10 2 1 10 13 3 NA 11 14 4 3 NA 7 5 4 13 22 现在假设我
我在 R 中运行一个具有大量时间和位置固定效应的回归。我尝试将一个漂亮的汇总表输出到 Latex 中。我从 stargazer 包切换到 huxtable,因为 stargazer 在忽略固定效果时表
我想删除一个属性并返回一个新对象而不改变原始对象。 我知道我们可以像这样使用 Lodash 轻松做到这一点: const profile = { name: 'Maria', age: 30 } _.
我正在通过更改一些内容来修改 javascript 对象。当我重新创建它时,我会得到每个 key 对的索引号。 "0":{...},"1":{...}, 如何删除/省略这些 0、1、2、3、4 数字的
我正在一个非常方便且名称丰富的网站 here 上完成示例之一。 ,具体来说: func applyMutliplication(value: Int, multFunction: Int -> Int
这个问题在这里已经有了答案: Why do java source files require package declarations? (4 个答案) 关闭 6 年前。 我是 Java 的新手,
在下面的代码中: Widget makeWidget() { return Widget(); } void foo(Widget widget) { ... } foo(makeWid
这是我使用下面的调用调用的过程: CALL abc('01-04-2011','14-04-2014','28,29,36,37,38','33,34,35,41,42,43') 但问题是下面提到的查
嘿,我正在寻找一种在 yui 数据表中省略文本的好方法。我的意思是,格式化文本,使其很好地适合其单元格,并且如果文本必须被 chop ,则在其后面有一个椭圆 (...)。 我想在不使用 CSS 选择器
我有一个如下表(记录)。 ID Status AA124 Pass AA125 Pass Z_AA134 Fail Z_AA135
我是一名优秀的程序员,十分优秀!