具有空初始化的对象的生命周期

gez*_*eza 2 c++ object-lifetime language-lawyer c++17

目前的标准草案在[basic.life/1]中说(以前的标准有相似的措辞):

对象或引用的生命周期是对象或引用的运行时属性.如果一个对象属于类或聚合类型,并且它或其子对象之一由除了普通默认构造函数之外的构造函数初始化,则称该对象具有非空的初始化.[注意:通过简单的复制/移动构造函数进行初始化是非空的初始化. - 结束注释]类型T对象的生命周期从以下开始:

(1.1)获得具有适当对齐和T型尺寸的存储,并且

(1.2)如果对象具有非空的初始化,则其初始化完成,

看到这段代码:

alignas(int) char obj[sizeof(int)];
Run Code Online (Sandbox Code Playgroud)

basic.life/1是否意味着这里int(和其他几种类型,具有相同或更小的对齐/尺寸要求int)已经开始了它的生命周期?

这甚至意味着什么?如果一个对象已经开始它的生命周期,它是否被创建?[intro.object/1]说:

[...]通过定义([basic.def]),通过new-expression,隐式更改union的活动成员([class.union])或创建临时对象时创建对象([conv.rval],[class.temporary])[...]

因此,根据这一点,我obj(作为int)不是创建的.但它作为一个int(以及其他可能是无限类型的空间可初始化对象)的生命已经开始.

我很困惑,你能澄清一下吗?

Nic*_*las 8

除非已创建对象,否则无法开始对象的生命周期.并且[intro.object]/1定义了创建对象的唯一方法:

当隐式更改union(12.3)的活动成员或创建临时对象时(7.4,15.2),定义(6.1),new-expression(8.3.4)创建对象.

此定义创建的对象是类型char[].因此,这是生命周期开始的唯一对象.并且此构造不会创建其他对象.

为了使这种解释更可靠,存在C++ 20 P0593的提议,其主要目的是允许该声明隐式地创建其他此类对象.


评论:

(1.2)中的条件仍困扰着我.为什么会这样?

它就在那里,因为对于没有经过初始化的对象,它不能说"初始化已完成".

假设我new(obj) int之后有.这显然创造了一个int对象.但在此之前,obj已经获得了必要的存储空间.

不,obj为类型对象获取存储的声明char[].获取int正在创建的对象的存储的是new(obj).是的,placement-new表达式获取它创建的对象的存储空间.就像变量声明获得它创建的对象的存储一样.

仅仅因为存储恰好存在并不意味着它没有获得.


asc*_*ler 5

我解释

类型对象的生命周期T从...开始

意思是

鉴于程序创建了一个对象T,下面描述了该对象的生命周期何时开始......

并不是

如果满足以下条件,则T存在类型的对象,并且其生命周期开始于......

也就是说,存在一个隐含的附加条件,即以[intro.object]/1中描述的某种方式"创建"对象.但是段落[basic.life] 1 /并不意味着它本身意味着存在任何对象,只存在一个存在的对象的属性.

因此,对于您的声明,文本描述了一个类型对象char[sizeof(int)]和一个或多个类型对象的生命周期的开始char(即使声明是块作用域中的语句并且没有初始化),但由于没有对象在int隐含存在的类型中,我们不会说出这样一个对象的生命周期.

  • @geza它基本上说静态初始化命令惨败是危险的。具有静态存储持续时间的对象具有“程序持续时间”的存储,但是,如果具有静态存储持续时间的类类型的对象需要尚未开始的构造函数调用,则不能使用该对象,除非在少数明确允许的方式。 (2认同)