在编译一个相当简单的c ++ 11程序时,gcc和clang之间的结果不同

Ili*_*llo 56 c++ gcc clang c++11

我试图了解这个简单的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;   
}
Run Code Online (Sandbox Code Playgroud)

如图所示,我正在尝试使用统一初始化来初始化一个大小的匿名(resp.命名)多维数组3x3.使用MacPorts中的gcc 4.7进行编译时,可以获得预期的输出:

$g++-mp-4.7 -std=c++11 dyn_matrix.cpp -o dyn_matrix 
$ ./dyn_matrix
2
2
$
Run Code Online (Sandbox Code Playgroud)

相反,在使用clang的情况下,输出读取:

$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang
$ ./dyn_matrix_clang 
2
4
$  
Run Code Online (Sandbox Code Playgroud)

在这种情况下,结果(显然)是错误的.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
Run Code Online (Sandbox Code Playgroud)

谁应该受到责备?我,gcc还是clang?

更新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.

谢谢.

Mat*_* M. 20

更新:感谢Faisal Vali和Richard Smith,这个错误已在Clang ToT中得到纠正; 查看提交引入的测试文件.


根据§8.5.1[dcl.init.aggr],看来Clang错了:

11/Braces可以在初始化列表中省略,如下所示.如果初始化列表以左括号开头,则后续的逗号分隔的initializer-clause列表初始化子集合的成员; 如果有比成员更多的初始化子条款是错误的.但是,如果子聚合的初始化列表不以左括号开头,则只从列表中获取足够的初始化子句来初始化子聚合的成员; 剩下的任何初始化子句用于初始化当前子聚合为成员的聚合的下一个成员.[ 例如:

float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};
Run Code Online (Sandbox Code Playgroud)

是一个完全-支撑初始化:1,1,3和5初始化数组的第一行y[0],即y[0][0],y[0][1]y[0][2].同样,接下来的两行初始化y[1]y[2].初始化程序提前结束,因此y[3]初始化s元素,就像使用表单的表达式显式初始化一样float(),即初始化为0.0.在以下示例中,初始化列表中的大括号被省略; 但是初始化列表与上面示例的完全支撑的初始化列表具有相同的效果,

float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};
Run Code Online (Sandbox Code Playgroud)

y的初始化程序以左括号开头,但是for的初始化程序y[0]不是,因此使用列表中的三个元素.同样,接下来的三个是连续采取y[1]y[2].- 结束例子 ]

我认为因为§5.3.4[expr.new]而适用:

15/创建类型为T的对象的new-expression初始化该对象,如下所示:

  • 如果省略new-initializer,则默认初始化对象(第8.5节); 如果没有执行初始化,则该对象具有不确定的值.
  • 否则,根据§8.5的初始化规则解释new-initializer以进行直接初始化.