【发布时间】:2013-06-30 02:28:51
【问题描述】:
以下代码非常简单,我希望它应该可以正常编译。
struct A
{
struct B
{
int i = 0;
};
B b;
A(const B& _b = B())
: b(_b)
{}
};
我已经使用 g++ 版本 4.7.2、4.8.1、clang++ 3.2 和 3.3 测试了此代码。除了 g++ 4.7.2 对这段代码 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770) 的段错误之外,其他经过测试的编译器给出的错误消息并没有太多解释。
g++ 4.8.1:
test.cpp: In constructor ‘constexpr A::B::B()’:
test.cpp:3:12: error: constructor required before non-static data member for ‘A::B::i’ has been parsed
struct B
^
test.cpp: At global scope:
test.cpp:11:23: note: synthesized method ‘constexpr A::B::B()’ first required here
A(const B& _b = B())
^
clang++ 3.2 和 3.3:
test.cpp:11:21: error: defaulted default constructor of 'B' cannot be used by non-static data member initializer which appears before end of class definition
A(const B& _b = B())
^
使这段代码可编译是可能的,而且看起来应该没有什么区别。有两种选择:
struct B
{
int i = 0;
B(){} // using B()=default; works only for clang++
};
或
struct B
{
int i;
B() : i(0) {} // classic c++98 initialization
};
这段代码真的不正确还是编译器错误?
【问题讨论】:
-
我的 G++ 4.7.3 对这段代码说
internal compiler error: Segmentation fault... -
(错误 C2864: 'A::B::i' : 只有静态 const 整数数据成员可以在类中初始化)是 VC2010 所说的。该输出与 g++ 一致。 Clang 也这么说,尽管它的意义要小得多。您不能通过
int i = 0来默认结构中的变量,除非它是static const int i = 0。 -
@Borgleader:顺便说一句,我会避免将表达式
B()视为对构造函数的函数调用。您从不直接“调用”构造函数。将其视为创建临时B... 的特殊语法,并且构造函数仅作为该过程的一部分被调用,深入随后的机制。 -
嗯,向
B添加一个构造函数似乎可以在gcc 4.7中进行这项工作。 -
有趣的是,将 A 的构造函数的定义移出 A 似乎也使它工作(g++ 4.7);与“不能使用默认的默认构造函数......在类定义结束之前”的提示。
标签: c++ c++11 language-lawyer