2013-10-18 135 views
3

我最近发现你不能同时在类初始化和初始化列表中。 下面的代码失败:在类初始化和初始化列表

struct s 
{ 
    int i=0;  
}; 
int main() { 
    s s1; //s1.i = 0 
    //s s2={42}; //fails 
    return 0; 
} 

如果我删除了在类初始化,初始化列表中工作正常!

有人可以解释为什么这样的事情是不允许的?

+1

您确定您使用C++ 11模式进行编译吗?编译器是否真的实现了它?你有哪个编译器和哪个版本? –

回答

7

事实上,这在C++ 14中是允许的。

struct s 
{ 
    int i=0;  
}; 

int main() { 
    s s1; 
    s s2 = {42}; // succeeds 
} 

很可能您的编译器并未在C++ 14中实现新规则。然而,最新版本的clang接受这一点,并在C++ 14模式下执行正确的操作。

当将类内初始化添加到C++ 11时,它被指定为阻止类成为聚合。这是因为当时聚合概念与需要简单构建的PoD类型密切相关。拥有一个类内初始化意味着一个类型不再是可以构造的。然而,从那以后,这两个概念变得更加独立,因此对于C++ 14来说,一个反转该决定的简短提议就被接受了。

+0

它不符合GCC 4.8。 – thokra

+1

我不认为它在C++ 11中是合法的。看到我的答案。 – juanchopanza

+0

也没有铿锵声++ 5.0 – chrizke

4

这个初始化:

s s1 = { 42 }; 

要求s,或者说,它有一个有效的构造以e.g一个int或std::initializer_list

当您在声明的位置添加成员初始化时,您将类s渲染为非聚合,因此您不能再使用聚合初始化。

你可以通过添加一个构造函数中使用相同的初始化语法你非集合:

struct s 
{ 
    s(int i) : i(i) {} 
    int i=0;  
}; 

我相信这个限制已经放宽了对C++ 14。

查看What are aggregates...了解更多信息。

+0

这不是一个解释。问题是为什么聚合可能没有为其成员提供大括号或相等的初始值设定项。 –

+0

@ VladfromMoscow,因为标准是这样说的。这里没有任何解释,但我想人们意识到,放弃C++ 14的这个规则已经足够安全了。 – juanchopanza

+0

我也来到这个解决方法,但它正是我想避免 – Davidbrcz