编译一个相当简单的c ++ 11程序时,gcc和clang之间的不同结果
我试图了解在这个简单的C ++ 11程序的输出中由gcc和clang公开的不同行为是否是由于clang(Xcode 5.0.2,OS X 10.8.5)中的一个错误引起的。 代码如下:
#include <iostream> int main() { int matrix[][3]{{1,2,3}, {4,5,6}, {7,8,9}}; auto dyn_matrix = new int[3][3]{{1,2,3}, {4,5,6}, {7,8,9}}; std::cout << matrix[0][1] << std::endl; std::cout << dyn_matrix[0][1] << std::endl; return 0; }
如图所示,我试图使用统一的初始化来初始化一个大小为3x3
的匿名(名为)multidimensional array。 当用MacPorts编译gcc 4.7时,获得预期的输出:
$g++-mp-4.7 -std=c++11 dyn_matrix.cpp -o dyn_matrix $ ./dyn_matrix 2 2 $
相反,如果使用铛,输出读取:
$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang $ ./dyn_matrix_clang 2 4 $
在这种情况下,结果是(显然)是错误的。 clang --version
报道:
Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn) Target: x86_64-apple-darwin12.5.0 Thread model: posix
谁应该责怪? 我,海湾合作委员会或铿锵?
更新2013年12月11日:错误应该已经在r196995被修复。 不幸的是,我们仍然不知道在Apple更新Xcode附带的clang版本之前需要多长时间。
更新2013年12月9日:我提交了关于LLVM bugzilla平台的错误报告。 它确实被认为是一个错误,补丁正在审查中,请参阅http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20131209/095099.html 。
谢谢。
更新:感谢费萨尔·瓦利(Faisal Vali)和理查德·史密斯(Richard Smith),这个错误已经在Clang ToT中得到纠正; 请参阅提交引入的testing文件 。
根据§8.5.1[dcl.init.aggr] ,看起来Clang是错误的:
11 /大括号可以在下面的初始化列表中被忽略。 如果初始化器列表以左大括号开始,则后续逗号分隔的初始化子句列表初始化子聚集的成员; 有比成员更多的初始化子句是错误的。 但是,如果子集合的初始化符列表不是从左括号开始,那么只有从列表中select足够的初始化子句才能初始化子集合的成员; 任何剩余的初始化子句都将被初始化为当前子聚集所属的聚合的下一个成员。 [ 例如:
float y[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 }, };
是一个完全支撑的初始化:1,3,5初始化数组
y[0]
的第一行,即y[0][0]
,y[0][1]
和y[0][2]
。 同样,接下来的两行初始化y[1]
和y[2]
。 初始化器提前结束,因此初始化y[3]
元素,就像用float()
forms的expression式明确初始化一样,也就是用0.0
初始化。 在以下示例中, 初始化程序列表中的大括号将被省略。 然而, 初始化 列表与上面例子的完全支撑的初始化 列表具有相同的效果,float y[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 };
y的初始值设定项以左大括号开头,但是
y[0]
不是,因此使用列表中的三个元素。 同样,接下来的三个是为了y[1]
和y[2]
。 – 结束示例 ]
我认为适用于§5.3.4[expr.new] :
15 /创buildtypesT的对象的新expression式如下所示初始化该对象:
- 如果省略了new-initializer ,则该对象将被默认初始化(第8.5节 )。 如果没有执行初始化,则该对象具有不确定的值。
- 否则,按照§8.5的初始化规则对新的初始化器进行解释直接初始化。