【发布时间】:2018-08-08 20:17:42
【问题描述】:
在深入研究动态内存的过程中,我突然想到,琐碎的类型如何开始它们的生命周期似乎是矛盾的。考虑sn-p
void* p = ::operator new(sizeof(int)); // 1
// 2
new (p) int; // 3
int 的生命周期何时开始?
-
只获取存储,指定
::operator new有效果(来自[new.delete.single])new-expression 调用的分配函数,用于分配 size 字节的存储空间。 [...] 分配适当对齐的存储空间,以表示该大小的任何对象,前提是该对象的类型没有新扩展对齐。
鉴于在创建对象时获取存储空间is insufficient,
int不能在此处开始其生命周期。 此时,
int的合适存储空间已获得。-
int是由放置 new 创建的。但不知何故,它的生命周期并没有从这里开始,因为从 [basic.life][...] 如果一个对象是一个类或聚合类型,并且它或它的一个子对象由一个普通的默认构造函数以外的构造函数初始化,则称它具有非空初始化。
T类型对象的生命周期开始于:获得了与
T类型正确对齐和大小的存储,并且如果对象有非空初始化,则其初始化完成[...]
int既不是类也不是聚合类型,因此它的初始化是空的。因此只有第一个项目符号适用。但是,这显然不是获得存储的时间,因此不可能是其生命周期开始的时间。
一些上下文
分配器are required 在不构造其元素的情况下返回内存。然而,这对于平凡的类型没有意义。 a.allocate(n) 与 a 类型 T 的分配器对象的效果是
为
T类型的n对象分配了内存,但未构造对象。
【问题讨论】:
-
相关“constructing” a trivially-copyable object with memcpy 有several linked questions 涵盖了这个主题的几个变体,其中一个几乎肯定会涵盖这个案例。
-
相关的是 P0593(最近更新了修订版 2),尽管到目前为止还没有提出对标准的具体更改
-
这不是其他线程的欺骗(placement-new 与
memcpy或其他线程有很大不同)。该线程的原始标题对其提出的真正问题具有误导性 -
@M.M:但是the answer is the same。根据 [intro.object]/1,放置
new是导致创建对象的原因。你不能开始一个不存在的对象的生命周期。 -
@NicolBolas 您链接的答案中没有任何内容适用于这个问题。在这个问题的代码中有 is 一个由placement-new创建的对象;该答案(以及它所回答的问题)是关于没有创建对象的情况
标签: c++ language-lawyer object-lifetime placement-new object-model