问题描述
在下面的简短示例中,指针 f
指向的对象或刚从 main
返回之前用来指向的对象怎么说?
In the following short example, what can be said about the object the pointer f
points to or used to point to just before returning from main
?
#include <vector>
struct foo {
std::vector<int> m;
};
int main()
{
auto f = new foo;
f->~foo();
}
我相信不再有 f
用来指向的对象 foo
.我收到很多评论,认为这可能不正确,相反,可能有一个 foo
对象处于被破坏,死亡或无效的状态.
I believe that there is no longer an object foo
where f
used to point. I've received a lot of comments that this may not be correct and that instead there could be an object foo
in a destroyed, dead or otherwise invalid state.
对于存在被明确销毁但其存储仍然有效的对象,语言标准怎么说?
What does the language standard have to say about the existence of an objects that is explicitly destroyed but whose storage is still valid?
换句话说,可以合理地说在 f
上还有一个对象不在其寿命范围内吗?是否存在这样的事物,那就是它的生命周期没有结束,没有开始构造并且没有被破坏?
In other words, can it reasonably be said that there is still an object at f
that is outside of its lifetime? Is there such a thing as an object that is not in its lifetime, not begin constructed and not being destructed?
很明显,当对象不在其生命周期内时就可以存在.在建造和销毁过程中,有一个物体,其寿命尚未开始或已经结束.来自 https://timsong-cpp.github.io/cppwp/intro.object#1 :
It is clear that an object can exist when it isn't in its lifetime. During construction and destruction there is an object and its lifetime has not yet begun or as already ended. From https://timsong-cpp.github.io/cppwp/intro.object#1 :
但是在 f->〜foo();
之后,由 f
指向的对象(我们称其为 o
)是没有被构造,它就没有寿命,也没有被破坏.我对本节的理解是, o
不能再占用存储空间,因为它不在任何列举的情况下.似乎这意味着不再有 o
,并且不再有指向 o
的指针.矛盾的是,如果您有一个指向 o
的指针,那么该指针将指向 o
无法占据的存储空间.
But after f->~foo();
the object that was pointed to by f
(lets call it o
) is not being constructed, it is not in its lifetime and it is not being destructed. My reading of this section is that o
cannot occupy the storage anymore because it isn't in any of the enumerated situations. It seems like this implies that there is no o
anymore and that there can't be a pointer to o
anymore. By contradiction, if you had a pointer to o
then that pointer would point to storage which o
can't occupy.
如果没有对象了,那么 foo
具有什么样的值?似乎它唯一可能的明智值是指向对象的指针,这将与该语句相矛盾.请参阅此问题.
If there isn't an object anymore, then what kind of value does foo
have? It seems like the only sensible possible value it can have is a pointer to an object, which would contradict the statement. See this question.
推荐答案
在C ++中,对象本质上是 eternal .语言中没有什么可以使对象消失的.生命周期之外的对象仍然是对象,仍然占据存储空间,并且该标准具有特定的东西,您可以使用指向/引用超出其生命周期的对象的指针来完成
In C++, objects essentially are eternal. There's nothing in the language that makes an object disappear. An object that is outside of its lifetime is still an object, it still occupies storage, and the standard has specific things that you can do with a pointer/reference to an object which is outside of its lifetime.
仅当不可能有有效的指针/引用时,该对象才真正消失.当该对象占用的存储空间结束其存储持续时间时,就会发生这种情况.指向超出其持续时间的存储的指针是无效的指针,即使该地址本身以后再次变为有效,也是如此.
An object only truly goes away when it is impossible to have a valid pointer/reference to it. This happens when the storage occupied by that object ends its storage duration. A pointer to storage that is past its duration is an invalid pointer, even if the address itself later becomes valid again.
因此,通过调用析构函数而不是使用 delete f
(这也会取消分配存储空间), f
仍指向 foo类型的对象
,但该对象已超出其生存期.
So by calling the destructor instead of using delete f
(which would also deallocate the storage), f
remains pointing to an object of type foo
, but that object is outside of its lifetime.
我上面陈述的理由基本上可以归结为对支持未创建对象的概念所必需的规定不作任何规定的标准.
The justification for my above statements basically boils down to the standard having none of the provisions that it would need in order to support the concept of objects being uncreated.
该标准提供明确,明确的声明,说明何时某个对象将出现在一块存储中. [intro.object]/1 概述了确切的机制,引发对象的创建.
The standard provides clear, unequivocal statements about when an object comes to exist within a piece of storage. [intro.object]/1 outlines the exact mechanisms that provoke the creation of an object.
该标准提供了有关对象生命周期何时开始和结束的明确,明确的声明. [basic.life] 完全概述了这些内容,但是[basic.life]/1特别说明了对象的生存期何时开始和结束.
The standard provides clear, unequivocal statements about when an object's lifetime begins and ends. [basic.life] in its entirely outlines these things, but [basic.life]/1 in particular explains when an object's lifetime begins and ends.
标准不不提供有关对象何时不存在的任何声明(清晰或其他方式).该标准规定了对象的创建时间,生命周期的开始时间以及结束时间.但是从不会说它们何时停止存在于某个存储中.
The standard does not provide any statement (clear or otherwise) about when an object no longer exists. The standard says when objects are created, when their lifetimes begin, and when they end. But never does it say when they stop existing within a piece of storage.
也有关于以下形式的陈述的讨论:
There has also been discussion about statements of the form:
已添加重点.
过去时态的使用表明该对象不再位于该存储中.但是什么时候该物体停止停在那里?没有 clear 声明是什么导致了这种情况的发生.而且,没有了,这里过去时的使用就没关系了.
The use of the past-tense suggests that the object is no longer located in that storage. But when did the object stop being located there? There is no clear statement about what exactly caused that to happen. And without that, the use of past-tense here just doesn't matter.
如果您不能指出何时停止在那里的声明,那么您绝对可以说的是,标准中有几个地方可以清除措辞.并不能消除标准没有说明何时对象停止存在的明确事实.
If you can't point to a statement about when it stopped being there, then the absolute most you can say is that there are a couple of places in the standard with wording that could be cleaned up. It doesn't undo the clear fact that the standard does not say when objects stop existing.
但是它确实说明了何时无法再访问对象.
But it does say when objects are no longer accessible.
为了使某个对象停止存在,标准将必须考虑在这些对象不再存在时指向这些对象的指针.毕竟,如果指针指向一个对象,那么该对象必须仍然存在,对吧?
In order for an object to cease existing, the standard would have to account for pointers which point to those objects when they no longer exist. After all, if a pointer is pointing to an object, then that object must still exist, right?
[basic.compound]/3 概述了指出指针可以具有的状态.指针可以处于以下四种状态之一:
[basic.compound]/3 outlines the states that a pointer can have. Pointers can be in one of four states:
没有指向没有对象的指针的余量.允许使用无效的指针值",但仅当它们指向末端的存储空间的存储时间:
There is no allowance given for a pointer which points to no object. There is an allowance for an "invalid pointer value", but pointers only become invalid when the storage duration for the storage they point into ends:
请注意,该语句意味着所有指向此类对象的指针都不再位于对象的指针"中.状态并输入无效指针"状态.因此,此类存储中的对象(包括生命周期内外的对象)都将无法访问.
Note that this statement means that all pointers to such objects cease being in the "pointer to object" state and enter the "invalid pointer" state. Thus, objects within such storage (both within and outside of their lifetimes) stop being accessible.
这正是标准要支持不再存在的对象的概念所需要的那种语句.
This is exactly the sort of statement that would need to exist for the standard to support the concept of objects no longer existing.
但是没有这样的陈述.
[basic.life]确实有一些语句,它们解决了可以使用指向超出其生命周期的对象的指针的有限方式.但请注意其使用的特定措辞:
[basic.life] does have several statements that address limited ways that pointers to objects outside of their lifetime can be used. But note the specific wording it uses:
从不表示指针指向".分配的存储.它永远不会撤消[basic.compound]/3关于指针种类的声明.指针仍然是指向对象的指针.只是指针指的是分配的存储".并且该指针可以用作 void *
.
It never says that the pointer "points to" allocated storage. It never undoes [basic.compound]/3's declaration about the kinds of pointers. The pointer is still a pointer to an object; it's just that the pointer "refers to allocated storage". And that the pointer can be used as a void*
.
即,不存在诸如指向分配的存储的指针"之类的东西.存在指向对象寿命之外的对象的指针,其指针值可用于引用分配的存储".但是仍然是指向对象的指针".
That is, there's no such thing as a "pointer to allocated storage". There is a "pointer to an object outside of its lifetime, whose pointer value can be used to refers to allocated storage". But is still a "pointer to an object".
对象必须存在才能具有生命周期.该标准明确规定了这一点.但是,该标准在任何时候都没有将对象的存在与其生存期联系起来.
Objects must exist in order to have a lifetime. The standard makes that clear. However, the standard does not at any point link the existence of an object to its lifetime.
实际上,如果结束对象的生存期意味着该对象不存在,则对象模型的复杂程度将大大降低.[basic.life]的大多数内容都是关于在对象的生存期之外,使用特定的方法来使用对象的名称或对该对象的指针/引用.如果对象本身不存在,我们就不需要那种东西.
Indeed, the object model would be a lot less complicated if ending the lifetime of an object meant that the object didn't exist. Most of [basic.life] is about carving out specific ways you can use the name of an object or a pointer/reference to it outside of the lifetime of that object. We wouldn't need that sort of stuff if the object itself didn't exist.
有关此事的讨论中提到的是:
Stated in discussion about this matter was this:
如果的确如此, [basic.life]/8谈论这句话:
如果在对象的生命周期结束时指向原始对象的指针变为指向已分配内存的指针,为什么此语句谈论指向原始对象的指针?指针不能指向不存在的对象,因为它们不存在.
If pointers to the original object become pointers to allocated memory when the object's lifetime ends, why does this statement talk about pointers to the original object? Pointers can't point to objects that don't exist because they don't exist.
仅当那些对象在其生命周期之外继续存在时,此段落才有意义.不,它不仅仅在构造函数/析构函数内;本节中的示例清楚地表明了这一点:
This passage can only make sense if those objects continue to exist outside of their lifetimes. And no, it's not just about within the constructor/destructor; the example in the section makes that abundantly clear:
struct C {
int i;
void f();
const C& operator=( const C& );
};
const C& C::operator=( const C& other) {
if ( this != &other ) {
this->~C(); // lifetime of *this ends
new (this) C(other); // new object of type C created
f(); // well-defined
}
return *this;
}
C c1;
C c2;
c1 = c2; // well-defined
c1.f(); // well-defined; c1 refers to a new object of type C
虽然 operator =
确实调用了析构函数,但析构函数在使用 this
指针之前完成了.因此, [class.cdtor] 的特殊规定没有在创建新对象时将其应用于 this
.因此,新对象是在对旧对象的析构函数调用的外部中创建的.
While operator=
does call the destructor, that destructor finishes before the this
pointer is used. Thus, the special provisions of of [class.cdtor] does not apply to this
at the moment the new object is created. So the new object is created outside of the destructor call to the old one.
因此,很明显,超出其使用寿命"对象规则应始终有效.这不仅是针对构造函数/析构函数的规定(如果有的话,它会明确地指出这一点).这意味着在创建新对象之前,名称/指针/引用仍必须在其生命周期之外命名/指向/引用对象.
So it's very clear that the "outside its lifetime" rules for objects are meant to always work. It's not just a provision for constructors/destructors (if it was, it would explicitly call that out). This means that names/pointers/references must still name/point-to/reference objects outside of their lifetime until the creation of the new object.
要做到这一点,它们命名/指向/引用的对象必须仍然存在.
And for that to happen, the object they name/point-to/reference must still exist.
这篇关于对象生存期的结束与它不存在之间的关系是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!