14

在 C++11 中,以下两个语句都是合法的:

声明1。int a[8] = {};

声明2。int a[8]{};

但是,我更喜欢语句 1 而不是语句 2,因为我认为语句 1 更具表现力。

C++11 标准是否保证两个语句在语义上是等效的?

4

4 回答 4

19

从语义上讲,它们并不相同,很像复制/直接初始化:

8.5.4 列表初始化[dcl.init.list]

1 列表初始化是从花括号初始化列表初始化对象或引用。这样的初始化器称为初始化器列表,列表中以逗号分隔的初始化器子句称为初始化器列表的元素。初始化列表可能为空。列表初始化可以发生在直接初始化或复制初始化上下文中;直接初始化上下文中的列表初始化称为直接列表初始化,而复制初始化上下文中的列表初始化称为复制列表初始化。[...](强调我的)

原始答案,处理比较性能:不,该标准规定了算法的一些复杂性限制,但没有在这些问题上的性能。这最好留给编译器,但所有编译器都可能生成相同的代码。

考虑一下复制初始化与直接初始化。该标准仅指定它们是什么,它从未说一个必须比另一个更快,或者它们必须表现相同。这完全取决于编译器。

这是一件好事,因为编译器知道什么最适合该平台。如果标准确实施加了这样的限制,它可以说+必须比 快*,这是非常直观的。*但是想想一个为乘法构建的平台,它实际上用机器代码计算更快。为了符合标准,编译器必须不遗余力地翻译*成较慢的指令。

于 2013-02-14T09:03:10.227 回答
3

该标准仅定义了所谓的“可观察行为”,即 I/O 库调用和易失性数据读写的序列。没有速度要求。

您无法确定在实践中哪个更快。体面的编译器应该发出相同的代码,但有时编译器中存在错误,这些错误可能会影响代码发出。

于 2013-02-14T09:06:22.923 回答
3

是的,它们在语义上是等价的。

聚合(8.5.1,例如数组)上的列表初始化(8.5.4)执行聚合初始化(8.5.4p3b1)。聚合初始化不关心语法形式是直接初始化还是复制初始化;聚合初始化的规则在任何一种情况下都同样适用。特别是,聚合的成员总是从初始化列表的相应子句复制初始化。

有一个例外,几乎但不完全适用于您的情况;在没有足够的元素来初始化聚合的所有成员时,标准不清楚如何初始化剩余的成员;它们是从{}(空的列表初始化器)列表初始化的,但没有指定它们是复制列表初始化还是直接列表初始化,或者这是否取决于原始列表初始化(参见注释);事实上,clang 和 gcc 在这种极端情况下的行为不同。但是,这与您的情况无关,因为聚合成员类型是int,并且对于非类类型的列表初始化{}调用值初始化,即零初始化,无论语法形式如何(即int i{};int i = {};语义相同)。

有几个理由更喜欢=(复制初始化)语法:首先,它是标准在几乎所有示例中使用的形式(例外是 8.5.4p3 中的最后两个示例,其中一个示例在缩小转换时出现错误另一个演示从一个空的初始化列表进行初始化)。此外,正如您所说,它更具表现力;我还发现,在列表初始化聚合时,复制初始化语法更好地反映了聚合的元素本身是复制初始化的事实。

最后,=在一种情况下需要使用 without 语法:对象是具有构造函数的非聚合类类型explicit。因此,应该为这种情况保留直接列表初始化语法。

于 2013-02-14T16:17:42.067 回答
0

C++11 标准甚至不保证它int a[8] = {};int aVeryLongName[8] = {};.

于 2013-02-14T09:19:15.593 回答