值初始化 C++
Posted
技术标签:
【中文标题】值初始化 C++【英文标题】:Value initialization c++ 【发布时间】:2019-01-03 20:40:54 【问题描述】:在值初始化上阅读 cppreference,我得出了这个结论:
如果 T 是没有默认构造函数或具有 用户提供或删除的默认构造函数,对象为 默认初始化;
还有例子:
struct T3
int mem1;
std::string mem2;
T3() // user-provided default constructor
;
阅读文章默认initialization
如果 T 是非 POD(C++11 前)类类型,则构造函数为 考虑并受到针对空的重载决议 参数列表。选择的构造函数(这是默认的构造函数之一 构造函数)被调用为新的提供初始值 对象;
如果 T 是数组类型,则数组的每个元素都是 默认初始化;
否则,什么都不做:自动存储的对象 持续时间(及其子对象)被初始化为不确定 价值观。
这适用于示例,T是类类型,这意味着重载决策应该选择候选者来初始化值(用户提供的默认构造函数),但它是空的,所以mem1
应该保留不确定的值(这是真的)但同样应该是mem2
,但那是“默认初始化”为“”,这是为什么呢?它是否递归工作?类类型的 T 的每个成员都服从第一规则?
我现在很困惑。
2)如果 T 是一个类类型,其默认构造函数既不是 用户提供或删除(也就是说,它可能是一个类 隐式定义或默认的默认构造函数),对象是 零初始化,然后默认初始化,如果它有 非平凡的默认构造函数;
还有例子:
struct T1
int mem1;
std::string mem2;
; // implicit default constructor
mem1
被零初始化为 0,但是“非平凡”的默认构造函数是什么意思? mem2
也默认初始化为“”,但是我仍然不确定,“非平凡的默认构造函数”是什么意思?默认构造函数应该由编译器生成,但是它如何决定什么是非平凡的——如果非平凡的默认构造函数意味着它必须初始化对象——与上面相同的问题,是否意味着每个对象都使用默认构造函数初始化?
【问题讨论】:
记住:T3()
与T3() = default;
不相同,或者根本不写ctor(is与@987654331 相同@)。
参见en.cppreference.com/w/cpp/language/default_constructor - “平凡的默认构造函数”部分。
【参考方案1】:
应该是mem2,但那是“默认初始化”为“”,这是为什么呢?它是否递归工作?类类型的 T 的每个成员都服从第一规则?
你的怀疑是正确的。当您默认初始化类时,您默认初始化其每个成员,因为在您的构造函数中未指定初始化。由于std::string
有一个用户提供的默认构造函数,它被调用并将字符串对象初始化为空。
但是“非平凡”的默认构造函数是什么意思?
平凡的构造函数是什么都不做的构造函数。对于 T
类型,它的构造函数是微不足道的,如果
T
没有虚成员函数
T
没有虚拟基类
T
没有带有大括号或等号初始值设定项的非静态成员。
T
的每个直接基数都有一个简单的默认构造函数
类类型的每个非静态成员都有一个普通的默认构造函数
所以在T1
的情况下,您没有平凡的构造函数,因为std::string
的默认构造函数是不平凡的。
【讨论】:
【参考方案2】:这适用于示例,T 是类类型,这意味着重载决策应该选择候选者来初始化值(用户提供的默认构造函数),但它是空的,所以 mem1 应该保留未确定的值(多数民众赞成在true ) 但同样应该是 mem2,但那是“默认初始化”为“”,这是为什么呢?
如果你从member initializer list 中省略了一个数据成员,那么它会被默认初始化,这对于std::string
意味着调用它的默认构造函数并将其初始化为一个空字符串。您的默认构造函数没有成员初始化列表,因此所有成员都被默认初始化。
“非平凡”的默认构造函数是什么意思?
您可以找到一个简单的构造函数here 的要求。非平凡的默认构造函数只是一个默认构造函数,它不尊重平凡构造函数的所有要求。简而言之,一个微不足道的默认构造函数除了标记对象生命周期的开始之外,根本不做任何事情(甚至在幕后)。
是否意味着每个对象都使用默认构造函数进行初始化?
如前所述,默认构造函数(与任何其他构造函数一样)将默认初始化成员初始化器列表中未指定的任何数据成员。由于默认为空,默认构造函数将递归地导致默认初始化,除非内部成员使用成员初始化器列表指定替代初始化。
【讨论】:
以上是关于值初始化 C++的主要内容,如果未能解决你的问题,请参考以下文章