我有类似的代码:
class AClass {
public:
struct AStruct { };
AClass(){}
private:
const AStruct m_struct;
};
int main() {
AClass a;
}
error: constructor for 'AClass' must explicitly initialize
the const member 'm_struct'
如果我为struct AStruct
指定了C ++ 11默认构造函数,我会得到同样的错误:
struct AStruct {
AStruct() = default;
};
但是,这可以通过编写一个空体的构造函数来解决:
struct AStruct {
AStruct(){} // fixed
};
为什么我需要指定一个空构造函数?它不是通过结构的公共访问自动创建的吗?
为什么C ++ 11默认构造函数不能解决问题?
答案 0 :(得分:27)
来自§8.5[dcl.init] / 7:
如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型。
AClass
的默认构造函数默认初始化const
成员(见下文),因此该成员必须具有用户提供的默认构造函数。使用= default
不会导致用户提供的默认构造函数,如§8.4.2[dcl.fct.def.default] / 4中所示:
如果函数是用户声明的,并且未明确默认,则用户提供该函数 删除了第一份声明。
根据§12.6.2[class.base.init] / 8默认初始化成员:
在非委托构造函数中,如果给定的非静态数据成员或基类未由mem-initializer-id指定(包括没有mem-initializer-list的情况,因为构造函数没有ctor -initializer)并且实体不是抽象类的虚拟基类(10.4),然后是
- 如果实体是具有支撑或等于初始化程序的非静态数据成员,则按照8.5中的规定初始化实体;
- 否则,如果实体是匿名联合或变体成员(9.5),则不执行初始化;
- 否则,实体默认初始化(8.5)。
答案 1 :(得分:17)
从@ chris的答案中被盗我们有这一段:§8.5[dcl.init] / 7:
如果程序要求对const限定类型T的对象进行默认初始化,则T应为具有用户提供的默认构造函数的类类型。
然后我们可以构建一个完全荒谬的案例来说明这种限制:
struct Foo {};
int main() {
const Foo f;
}
无法按照标准规定在clang中编译。您的代码就是这样,但作为另一个类/结构的成员变量。
我们甚至可以这样做:
struct Foo {int x = 3;};
int main() {
const Foo f;
}
显然所有数据都已初始化。最后一个例子让我相信这是标准中的缺陷。
这个想法可能与POD类型未初始化和const
有关,但是措辞阻止了与之无关的代码。现代C ++中的默认构造函数通常都足够好,并且强制Foo(){}
形式不佳。