【问题标题】:What does it mean for an object to exist in C++?对象存在于 C++ 中意味着什么?
【发布时间】:2015-07-30 16:26:20
【问题描述】:

[class.dtor]/15 读取,强调我的:

一旦为对象调用析构函数,该对象不再存在;如果为生命周期已结束 (3.8) 的对象调用析构函数,则行为未定义。

但是,据我所知,这是标准中对“现有”对象的唯一引用。这似乎也与更具体的 [basic.life] 形成对比:

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

  • 如果T 是具有非平凡析构函数 (12.4) 的类类型,则析构函数调用开始,或者

  • 对象占用的存储空间被重用或释放。

我们在这里有两种不同的措辞:“对象的生命周期结束”和“对象不再存在”,前者只发生在非平凡的析构函数中,而后者发生在 any析构函数。差异有什么意义?不再存在的对象意味着什么?

【问题讨论】:

  • C++03 有同样的措辞。让我想知道是否只是粗制滥造需要一些清理。
  • @Tony:在 GCC(ideone 正在使用)上工作的很多东西不是标准的;在那里工作并没有真正的证据表明该标准特别说明了什么。 (我能想到的最大的事情是 GCC 对 C99 风格的 VLA 的支持)
  • @TonyD: int 不是类类型。这意味着生命周期由“对象占用的存储空间被重用或释放”定义。条款。 [class.dtor]/15 的第一个定义适用于类类型。
  • "exist" 大概与生命开始有关,即also unclear

标签: c++ c++11 language-lawyer c++14 object-lifetime


【解决方案1】:

引用的措辞似乎暗示编译器可以在其析构函数的开头正确插入代码,该代码将与对象关联的内存返回到堆中。但是这样做会消除对象在销毁期间引用其自身成员的能力,如果对象要能够自行销毁,则需要这样做。

所以我认为引用的措辞有问题,应该修复。

关于“一生”和“存在”的含义,我建议有一些不同的上下文,它们在其中意味着不同的东西:

在构造的上下文中,生命周期和存在从构造函数开始时开始。在该上下文之外,它们在构造函数结束时开始。

在析构函数的上下文中,生命周期和存在在析构函数结束时结束。在这种情况下,它们会在破坏开始时结束。

所以一个对象在构造过程中可能会引用它自己的成员,并可能将自己传递给其他对象的函数,这些函数可能会引用该对象及其成员,等等。但一般来说,对象(类的实例)可能不会被引用(不会产生未定义的行为),直到它们的构造函数之一完成。

对象的析构函数可以引用它自己的成员并调用其他(现有)对象的函数,这些对象可能引用被销毁的对象和/或其成员。但一般来说,一个对象在其析构函数启动后可能不会被引用。

这种多上下文定义对我来说最有意义,但我可以看到有人提出论点,即从为其分配内存到释放内存的那一刻,一个对象应该被认为是活动的, 我想说浅拷贝的内存应该在一个对象的构造函数启动时分配给它,并在它的析构函数结束时释放。

【讨论】:

  • 是的,我不知道我大脑中留下的那个区域是从哪里来的。但希望其余的答案或多或少是有效的。
  • 我不明白你是如何得出这样的结论的,即该措辞允许在析构函数完成之前释放内存。仅仅因为对象本身已经结束了它的生命周期,并没有说明它的成员的生命周期;这些成员在析构函数的 end 之前不会被销毁。
  • 好吧,如果对象“不存在”了,那是不是意味着它的浅拷贝内存可以被释放?如果对象在其析构函数中不存在,则不能说从该析构函数中删除 this->myMember。
  • "但一般来说,一个对象在其析构函数启动后可能不会被引用。" 我不明白你想说什么。众所周知,在析构函数达到} 之前,对象是完全可用的。
  • 我正在尝试解释标准。它似乎肯定是想说,例如,一旦析构函数开始,你就不能调用析构函数。 (或者,这样做可能会产生“未定义的行为”。)我的猜测是,如果编译器真正实现了标准,那么在析构函数的上下文之外,您也无法对对象执行任何其他操作打电话,但也许我错了。
猜你喜欢
  • 1970-01-01
  • 2020-10-12
  • 2016-01-02
  • 2012-05-29
  • 2018-04-21
  • 2011-01-02
  • 2014-02-08
  • 2016-10-02
  • 1970-01-01
相关资源
最近更新 更多