【问题标题】:Why is the concept of vacuous initialization necessary?为什么需要空初始化的概念?
【发布时间】:2021-11-12 04:45:29
【问题描述】:

虚初始化的概念在[basic.life/1]引入和使用,在C++标准的其他地方似乎没有用到:

对象或引用的生命周期是对象或引用的运行时属性。如果一个变量是默认初始化的,并且如果它是类类型或其(可能是多维的)数组,那么该类类型具有一个普通的默认构造函数,则称该变量具有空初始化T 类型对象的生命周期开始于:

  • 获得了具有适合T 类型的正确对齐和大小的存储,并且
  • 其初始化(如果有)已完成(包括空初始化)([dcl.init]),

由于空初始化是默认初始化的子集,因此对于类和数组类型是初始化,对于标量类型是无初始化(参见[dcl.init.general/7]),因此这两种情况都包含在“初始化(如果有)”这一短语中。

那么为什么需要空初始化的概念呢?

引用似乎等同于这个修改后的版本:

对象或引用的生命周期是对象或引用的运行时属性。 T 类型对象的生命周期开始于:

  • 获得了与 T 类型正确对齐和大小的存储,并且
  • 其初始化(如果有)已完成 ([dcl.init]),

【问题讨论】:

标签: c++ initialization language-lawyer object-lifetime


【解决方案1】:

由 OP 引用的当前标准草案已通过 CWG issue 22562256. 可轻易破坏的对象的生命周期)和 P1787R6P1787R6:声明和在哪里可以找到它们),之后,如果有的话,术语(而不是“概念”)可以用来统称“初始化”不够用的情况。

至少是从[stmt.dcl]/3引用的:

在函数内从 P 点到 Q 点的每次控制转移(包括语句的顺序执行)时,所有在 P 而不是在 Q 处处于活动状态的变量都按照其构造的相反顺序被销毁。然后,所有在 Q 处活动但在 P 处不活动的变量按声明顺序初始化; 除非所有此类变量都具有空初始化([basic.life]),否则控制权的转移不应是跳跃。 [...]

简单的“初始化”在这里自然是不够的,因为变量可能有非空初始化,这样在点 P 到点 Q 之间的跳转会违反 [stmt.dcl]/3 的限制。

如果我们按照提议修改 [basic.life/1],则该术语将不再被定义,例如[stmt.dcl]/3 需要明确写出允许跳转(在 P->Q 限制下)的完整初始化上下文。

【讨论】:

  • 谢谢,我没有注意到[stmt.dcl]/3 中使用了该定义(并且仅在那里)。
  • 但我不相信在整个标准中使用过一次的定义可以证明定义的合理性。开发人员或至少编译器开发人员或语言设计人员是否使用“空初始化”?
  • @Maggyero 作为一名非专业语言律师,我自己的经验是,微妙的终生主题是困难,您通常会看到著名的 LL 关于该主题的缺陷报告R. Smith 等专家。鉴于那个空洞的初始化。多年来已经发生了一些变化,可能同样可以删除 term 并将初始化上下文描述移动到 [stmt.dcl]/3。但是,虽然这看起来像是一种编辑性(“文本改组”)更改,但它会完全删除该术语,这可能会让编译器实现者和类似的人感到惊讶,而为数不多的实际上会使用该术语的人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-11
相关资源
最近更新 更多