C++ 为什么常量成员结构中需要构造函数?

C++ 为什么常量成员结构中需要构造函数?,c++,c++11,C++,C++11,我有一个类似的代码: 类AClass{ 公众: 结构结构{}; AClass(){} 私人: 构造结构mu结构; }; int main(){ a组; } 它抛出此编译错误(版本5.1): 错误:“AClass”的构造函数必须显式初始化 常量成员“m_struct” 如果我为struct AStruct指定一个C++11默认构造函数,我会得到相同的错误: struct结构{ AStruct()=默认值; }; 但是,这可以通过编写一个具有空主体的构造函数来解决: struct结构{ ASt

我有一个类似的代码:

类AClass{
公众:
结构结构{};
AClass(){}
私人:
构造结构mu结构;
};
int main(){
a组;
}
它抛出此编译错误(版本5.1):

错误:“AClass”的构造函数必须显式初始化
常量成员“m_struct”
如果我为
struct AStruct
指定一个C++11默认构造函数,我会得到相同的错误:

struct结构{
AStruct()=默认值;
};
但是,这可以通过编写一个具有空主体的构造函数来解决:

struct结构{
AStruct(){}//已修复
};
为什么我需要指定一个空构造函数?它不是通过结构的公共访问自动创建的吗


为什么C++11默认构造函数不能解决这个问题?

来自§8.5[dcl.init]/7:

如果程序调用const限定类型T的对象的默认初始化,则T应为具有用户提供的默认构造函数的类类型

AClass
default的默认构造函数初始化
const
成员(见下文),因此成员必须具有用户提供的默认构造函数。使用
=default
不会产生用户提供的默认构造函数,如§8.4.2[dcl.fct.def.default]/4所示:

如果函数是用户声明的,且未显式默认,或 在其第一次声明中删除


根据§12.6.2[class.base.init]/8,默认初始化成员:

在非委托构造函数中,如果给定的非静态数据成员或基类未由mem初始值设定项id指定(包括由于构造函数没有ctor初始值设定项而没有mem初始值设定项列表的情况),并且实体不是抽象类的虚拟基类(10.4),则

-如果实体是具有大括号或相等初始值设定项的非静态数据成员,则按照8.5中的规定初始化实体
-否则,如果实体是匿名联盟或变体成员(9.5),则不执行初始化
-否则,实体默认初始化(8.5)。


从@chris的答案中我们得到了这一段:§8.5[dcl.init]/7:

如果程序调用const限定类型T的对象的默认初始化,则T应为具有用户提供的默认构造函数的类类型

然后我们可以构造一个完全荒谬的例子来说明这种限制:

struct Foo {};
int main() {
  const Foo f;
}
按照标准的要求,它不能以铿锵的声音编译。您的代码就是这样,但是作为另一个类/结构的成员变量

我们甚至可以这样做:

struct Foo {int x = 3;};
int main() {
  const Foo f;
}
所有数据都已初始化。最后一个例子让我相信这是标准中的一个缺陷


这种想法可能与POD类型未初始化和
const
有关,但措辞会阻止不相关的代码。现代C++中的默认构造函数通常不够好,并且强制<>代码>(){{} /COD> >格式很差。

使用<代码> AgStuts< /C>和<代码> AClass < /C> >非常令人困惑,尤其是因为这两个类都是类。你不能想出更好的名字吗?这里有一个。你不必提供默认构造函数,初始化
const
成员的值就足够了-@chris我使用G++-4.8。没有错误。我甚至可以毫无错误地调用
struct a
的const方法。那么,这个问题是不是很具体?这段代码实际上做了一些事情(而且很有用),但是我们得到了一个编译器错误@PengZhang G++4.8在这里违反了标准,而不是叮当声。@Casey@chris,为了更强调这个怪癖,如果
=default
是在类声明之外定义的,那么它将被视为用户定义的构造函数,并编译(8.4.2/5)@Niall,实际上我已经处理过了:)如果函数是用户声明的,并且在第一次声明时没有显式地默认或删除,那么它就是用户提供的。