【问题标题】:Does storage reuse really require object destruction?存储重用真的需要对象销毁吗?
【发布时间】:2021-11-08 21:00:35
【问题描述】:

根据[basic.life/1](我的粗体强调):

T 类型对象的生命周期开始于:

  • 存储具有适合类型 T 的正确对齐和大小,并且
  • 它的初始化(如果有)已完成(包括空初始化)([dcl.init]), 除了如果对象是联合成员或其子对象,它的生命周期仅在联合成员是联合中的初始化成员([dcl.init.aggr]、[class.base.init])或如中所述时才开始[class.union] 和 [class.copy.ctor],以及 [allocator.members] 中描述的除外。

类型 T 的对象 o 生命周期在以下时间结束:

  • 如果 T 是非类类型,则对象被销毁,或者
  • 如果 T 是类类型,析构函数调用开始,或者
  • 对象占用的存储空间被释放,或被未嵌套在 o ([intro.object]) 中的对象重用

所以我们有:

|------------|----|--------------|----------|-------------|----|--------------|

 <---------->      <------------> <--------> <----------->      <------------>
  storage           object         object     object             storage
  allocation        construction   lifetime   destruction        deallocation

              <----------------------------------------------->
               storage duration

根据[basic.life/8](我的粗体强调):

如果在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,在原对象占用的存储位置创建一个新的对象,指针指向原始对象的引用、指向原始对象的引用或原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,就可以用来操作新对象,如果原始对象可以被新对象透明地替换(见下文)。

想到两个问题:

  1. 放置new 运算符是重用存储的唯一方法吗?
  2. [basic.life/8] 中指定的结果是否真的需要销毁原始对象(即条件“在对象的生命周期结束后”)?

【问题讨论】:

  • 2.可以,但不应该,因为这个要求使联合在 C++ 中不可用(如果联合成员最初不是活动的,则不可能使其活动,因为创建成员类型的对象不会使成员的名称引用到新的[子]对象)
  • @LanguageLawyer 你的意思是在this answer的代码中的成员赋值运算符中需要声明name.~basic_string();吗?
  • @Maggyero:这是必需的,因为您需要销毁该对象,因为它是一个重要的析构函数,您的代码依赖于调用它来释放内存。
  • 不,对象的生命周期仅因存储重用而结束。这对于 [basic.life]/8 来说已经足够了。 Mebby 我的第一条评论令人困惑。不需要显式的析构函数调用,但也不应该是生命周期结束。
  • @LanguageLawyer 关于 2,好的,所以我们同意应该从标准中删除“对象生命周期结束后”的条件,因为原始对象的生命周期无论如何都会因存储重用而结束。

标签: c++ language-lawyer storage object-lifetime placement-new


【解决方案1】:

正如您所引用的,如果您将存储重新用于新对象,则该存储中的旧对象的生命周期将结束(除非新对象嵌套在旧对象中)。因此,如果您在包含现有对象的存储中创建一个新对象,那么现有对象将不再存在。

放置new操作符是重用存储的唯一方法吗?

“重用”这个词不是艺术术语;这只是英语。任何在存储中创建对象的东西都会“重用”存储。例如,construct_at 也可以重复使用存储空间。

【讨论】:

  • construct_at 基本上只是放置新的包装器:eel.is/c++draft/specialized.construct#2
  • 创建新对象的所有方法都在这里:eel.is/c++draft/intro.object#1.sentence-2.
  • 大约2,那么您是否同意应该从标准中删除“对象生命周期结束后”的条件,因为原始对象的生命周期无论如何都会因存储重用而结束?跨度>
  • 关于1,除了放置newconstruct_at之外,目前还有哪些C++结构允许存储复用?
  • @Maggyero: "你是否同意'在对象的生命周期结束之后'的条件应该从标准中删除,因为原始对象的生命周期无论如何都会因存储重用而结束?” 不,因为它专门讨论的是对特定对象的指针/引用或名称。注意到这个对象的生命周期已经结束是其中的一部分。
猜你喜欢
  • 2012-06-25
  • 2020-04-06
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多