C++ 带类内初始化的默认构造函数的行为是什么?
假设如下:C++ 带类内初始化的默认构造函数的行为是什么?,c++,c++11,C++,C++11,假设如下: class foo { public: foo() = default; private: std::string m_str = "Hello"; }; 我在cppreference.com或C++11草稿上找不到任何说明默认构造函数将如何处理m_str的文档。我的自然假设是,如果编译器已经在类中初始化过,那么它足够聪明,不会在默认构造函数中初始化m_str,但可能我错了 有人能解释一下这里的初始化行为吗?是否有任何担保或未指定?这在[class.ctor]/5中有明确
class foo
{
public:
foo() = default;
private:
std::string m_str = "Hello";
};
我在cppreference.com或C++11草稿上找不到任何说明默认构造函数将如何处理m_str的文档。我的自然假设是,如果编译器已经在类中初始化过,那么它足够聪明,不会在默认构造函数中初始化m_str
,但可能我错了
有人能解释一下这里的初始化行为吗?是否有任何担保或未指定?这在[class.ctor]/5中有明确的定义和规定: […]隐式定义的默认构造函数执行类的初始化集,该初始化集将由用户编写的默认构造函数在没有ctor初始值设定项(12.6.2)和空复合语句的情况下为该类执行。[……] 因此,默认构造函数执行与以下相同的操作:
foo() {}
这反过来会将大括号或相等的初始值设定项适当地应用于每个数据成员(参见[class.base.init]/8)。您用于
m_str
的初始化形式被标准称为大括号或相等的初始值设定项
在初始化器下的第一段中,标准规定:
8.5初始化器
1声明器可以为所声明的标识符指定初始值。标识符指定正在初始化的变量。8.5剩余部分中描述的初始化过程也适用于其他语法上下文指定的初始化,例如使用argument表达式初始化函数参数(5.2.2)或初始化返回值(6.6.3)
相当于:
foo(){}
foo() : m_str("Hello") {}
当使用没有成员初始值设定项列表的默认构造函数时,成员数据将默认初始化。在默认初始化过程中,对于具有大括号或equal初始值设定项的成员,该表单用于初始化它们。就你而言
foo(){}
相当于:
foo(){}
foo() : m_str("Hello") {}
你的意思是will从类中提取初始值设定项。cppreference在同一页上解释了它,其中谈到了类内初始值设定项:@KerrekSB Google不能帮我解决这个问题!“空复合语句”表示值初始化,对吗?@void.pointer他一定是指“我添加该语句是为了改进我的帖子”。此外,空的复合语句仅表示构造函数在分配和初始化步骤后不执行任何操作,初始化的类型(值/默认值/零…)取决于如何创建实例,而不是取决于构造函数的代码:)@Drax:No,它应该说“我在帖子中已经说过了”:-)当dyp发布注释时,我正在查找引用。@void.pointer:它的意思是“空函数体”,只是用语法表示。迂腐的评论:我认为NSDMI在这种情况下执行复制初始化,而
m_str(“Hello”)
执行直接初始化。@dyp您能详细说明一下吗?@dyp作为一种跟进,仍然与我的原始问题有关:当构造函数中未指定大括号或相等的初始化成员时,它是“复制初始化的”。这是否意味着它最初被建造,现在被复制?这似乎效率低下。@void.pointer复制初始化和直接初始化在[dcl.init]/17中指定。如果您对NSDMI使用大括号,您将获得列表初始化(直接列表初始化或复制列表初始化)。@dyp仍然不清楚。我在问为什么要使用复制初始化这个术语。这对我来说意味着两个阶段的初始化(初始默认构造,然后复制构造)。