C++ 在编译相当简单的c++;11计划

C++ 在编译相当简单的c++;11计划,c++,gcc,c++11,clang,C++,Gcc,C++11,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}}; st

我试图理解在这个简单的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;   
}
相反,如果使用clang,则输出读取:

$ clang++ -std=c++11 -stdlib=libc++ dyn_matrix.cpp -o dyn_matrix_clang
$ ./dyn_matrix_clang 
2
4
$  
在这种情况下,结果(显然)是错误的<代码>叮当声--版本报告:

Apple LLVM version 5.0 (clang-500.2.75) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix
谁该受责备?我,gcc还是叮当

2013年12月11日更新:该漏洞应该在r196995中修复。不幸的是,我们仍然不知道苹果需要多长时间才能更新Xcode附带的clang版本


2013年12月9日更新:我提交了一份关于LLVM bugzilla平台的错误报告。它确实被认为是一个bug,目前正在审查一个补丁,请参阅


谢谢。

更新:感谢费萨尔·瓦利和理查德·史密斯,这个错误已在Clang ToT中得到纠正;请参阅提交引入的


根据§8.5.1[dcl.init.aggr]的规定,似乎Clang是错误的:

11/括号可以在初始值设定项列表中省略,如下所示。如果初始值设定项列表以左大括号开始,则后续的逗号分隔的初始值设定项子句列表将初始化子集合的成员;初始化条款比成员多是错误的。但是,如果子集合的初始值设定项列表不以左大括号开头,则仅从列表中选取足够的初始值设定项子句来初始化子集合的成员;剩下的任何初始值设定项子句都留作初始化当前子集合所属集合的下一个成员。[示例:

是一个完全用括号括起来的初始化: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
};
y的初始值设定项以左大括号开始,但
y[0]
的初始值设定项不以左大括号开始,因此使用列表中的三个元素。同样,接下来的三个元素依次用于
y[1]
y[2]
-结束示例]

我认为这适用于§5.3.4[解释新内容]

15/创建类型为T的对象的新表达式初始化该对象,如下所示:

#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;   
}
  • 如果省略了新的初始值设定项,则对象默认已初始化(§8.5);如果未执行初始化,则对象的值不确定
  • 否则,新的初始值设定项将根据§8.5的初始化规则进行解释,以进行直接初始化

Visual Studio 2013表示,另一项统计数据为
2
。+1表示提出了一个有趣的好问题。确认OS X 10.7.5上的
clang++
v4.2也会生成代码输出“2 4”。我的直觉说这是错误的。我当前安装的clang版本在此代码上崩溃(clang版本3.4(trunk 193991))。是时候更新了,看看这是否更好了……我刚刚尝试了
clang 3.4(trunk 187030)
,我可以确认它在试图编译代码时崩溃了。下面是一个更完整的实时演示:@Dave
matrix
是一个
int[3][3]
dyn\u matrix
是一个
int(*)[3]
,所以
sizeof
对+1没有帮助。你第二句话的最后一句基本上是这么说的。初始值设定项的解释是相同的(因为它们在代码段中是相同的,所以输出也必须是相同的)。@Damon:我希望如此,但过去的经验表明,对于标准中的每个绝对值,至少有一个异常隐藏在不相关的段落中。。。甚至不算只有当
{…}
确实是一个新的初始值设定项时,这才适用:/I在LLVM bugzilla平台上提交了一份错误报告。它确实被认为是一个bug,目前正在审查一个补丁,请参阅。我将编辑原始问题以反映更改。起初我没有注意到您已经报告错误已修复。无论如何,主要问题已经修改,以反映更新。谢谢
float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};