c++ - 没有默认构造函数的类对象的值初始化
问题描述
我试图了解C++11 中T()
类T{}
类型的值初始化的确切行为。T
让我感到困惑的是这两个摘自http://en.cppreference.com的片段:
值初始化的影响是:[...]
1) 如果 T 是没有默认构造函数的类类型,或者具有用户提供或删除的默认构造函数的类类型,则该对象是默认初始化的;(C++11 起)
[...]
所以我查找了Default-Initialization:
默认初始化的效果是:
- 如果 T 是 [...] 类类型,则考虑构造函数并针对空参数列表进行重载决议。调用选择的构造函数(默认构造函数之一)为新对象提供初始值;
[...]
所以这基本上说如果 T 是一个类类型并且它的隐式默认构造函数不可用,那么对象将通过调用其默认构造函数之一来构造?据我了解,这仅对上述用户提供的默认构造函数有意义;然后,在构造时,只会执行该构造函数中明确说明的内容,并且每个未明确初始化的成员都将默认初始化(如果我在这里错了,请纠正我)。
我的问题:
1)如果没有用户提供的默认构造函数并且没有默认构造函数或者被删除会怎样?我猜代码不会编译。如果这是正确的,那么:
2)还需要明确提及“无默认构造函数”和“已删除默认构造函数”的情况?
解决方案
cppreference 上的措辞似乎与标准中的措辞不符。C++11 8.5/7 [dcl.init]:
对类型对象进行值初始化
T
意味着:
- if
T
是具有用户提供的构造函数(12.1)的(可能是 cv 限定的)类类型(第 9 条),则调用 for 的默认构造函数(如果没有可访问的默认构造函数T
,则初始化格式错误);T
- if
T
是没有用户提供的构造函数的(可能是 cv 限定的)非联合类类型,则该对象被零初始化,并且如果T
' 的隐式声明的默认构造函数不平凡,则调用该构造函数。- 如果
T
是数组类型,则每个元素都是值初始化的;- 否则,对象被零初始化。
一个值初始化的对象被认为是被构造的,因此受制于适用于“构造的”对象、“构造函数已完成的对象”等的本国际标准的规定,即使没有为对象的构造函数调用构造函数。初始化。
为了比较,这是 C++14 (n4140) 8.5/7 [dcl.init] 中的措辞:
对类型对象进行值初始化
T
意味着:
- 如果
T
是(可能是 cv 限定的)类类型(第 9 条),没有默认构造函数 (12.1) 或用户提供或删除的默认构造函数,则该对象是默认初始化的;- if
T
是一个(可能是 cv 限定的)类类型,没有用户提供或删除的默认构造函数,则该对象被零初始化并检查默认初始化的语义约束,如果T
有一个非平凡的默认构造函数,则对象是默认初始化的;- 如果
T
是数组类型,则每个元素都是值初始化的;- 否则,对象被零初始化。
一个值初始化的对象被认为是被构造的,因此受制于适用于“构造的”对象、“构造函数已完成的对象”等的本国际标准的规定,即使没有为对象的构造函数调用构造函数。初始化。
推荐阅读
- python - 将列表中的项目与包含列表的列中的项目匹配
- mysql - 如何一次性解决慢查询?
- wpf - WPF TreeView中的文本框不更新源
- c# - 如何在 asp.net 核心 web api 中返回 MimeKit.MimeMessage?它在控制器中运行良好,但在 Web Api 中运行良好
- regex - 用于从 AWS ARN 中提取区域名称的正则表达式
- html - 为什么用html编码后chrome上什么都没有?
- json - 我无法使用 Python3 解析嵌套 JSON 文件并将其加载到 postgres 中
- jsp - servlet 容器中的问题,两次获取 servlet 位置
- docker - 权限被拒绝从 Docker 容器中读取挂载的卷
- flutter - 在处理颤动之前删除listerers