I have an Animal
struct that has Dog
struct as a data member, my question is why the Dog
instance that is created (inside the Animal
) is still accessible through the allocated instance of Animal
even after the Dog
is destroyed (as shown in the output)
我有一个将Dog Struct作为数据成员的Animal结构,我的问题是为什么即使在Dog被销毁之后(如输出所示),创建的Dog实例(在Animal内部)仍然可以通过分配的Animal实例进行访问
struct Dog {
Dog() {}
Dog(std::string n) : name(n) {std::cout << "dog constructed\n";}
~Dog() {std::cout << "dog destructed\n";}
std::string name;
};
struct Animals {
Animals() {std::cout << "animal constructed\n";}
~Animals() {std::cout << "animal destructed\n";}
Dog dog;
};
Animals* foo() {
Animals* animals = new Animals;
animals->dog = Dog("layka");
return animals;
}
int main() {
Animals* animals = foo();
std::cout << animals->dog.name << std::endl;
delete animals;
}
Output:
产出:
animal constructed
dog constructed
dog destructed
layka
animal destructed
dog destructed
Also could someone please explain why animal is destroyed before the dog? and why it's destroyed twice while only constructed once?
还有谁能解释一下为什么动物在狗之前就被销毁了吗?为什么它被毁了两次,而只建了一次?
I wasn't expecting dog.name
to have the same value after it has been destroyed
我没想到Dog.name在被销毁后还会有同样的价值
更多回答
If you have an object that has passed its life-time, that has been destructed, you simply should not allow the code you use that object any more. If the code allows it, then it has undefined behavior.
如果你有一个对象已经过了它的生命周期,并且已经被销毁了,你就不应该再允许你使用这个对象的代码了。如果代码允许,则它具有未定义的行为。
With that said, I think you misunderstand the copying that happens with the assignment animals->dog = Dog("layka")
. You create a temporary Dog
object, it gets copied into animals->dog
, then the temporary object is destructed. The copy still lives on.
话虽如此,我认为你误解了作业动物->狗=狗(“Layka”)所发生的复制。你创建一个临时狗对象,它被复制到动物->狗中,然后这个临时对象被销毁。这本书的复制品还活着。
okay but why the copy still lives on, isn't it created on the stack? I know it's part of the allocated animal
object, but (I think) that isn't enough for the dog
object to have its lifetime extended.
好的,但是为什么副本仍然存在,它不是在堆栈上创建的吗?我知道它是分配的动物对象的一部分,但(我认为)这还不足以延长狗对象的生命周期。
The object that animals
is pointing to have its own Dog
object. As long as this Animals
object is alive, its embedded Dog
object is alive. You copy the temporary Dog
object into this animals->dog
object. And because you create that Animals
object on the heap, all its embedded member variables and object are also stored on the heap. They are included in the Animals
object itself.
动物所指向的对象有自己的Dog对象。只要该Animals对象是活动的,其嵌入的Dog对象就是活动的。您将临时狗对象复制到这个动物->狗对象中。因为您在堆上创建了Animals对象,所以它的所有嵌入的成员变量和对象也都存储在堆上。它们包含在Animals对象本身中。
Lets take another example: struct A { int d; };
. Now you do A* a = new A; a->d = 5;
. Would you consider the value 5
disappearing from the A
object that a
is pointing to? It's really the same thing if the member is an instance of a class (an object).
让我们举另一个例子:struct A{int d;。现在你做A*a=new A;a->d=5;。您认为值5会从a所指向的A对象中消失吗?如果该成员是一个类(一个对象)的实例,则情况实际上是一样的。
animal constructed
dog constructed: some temporary Dog("layka")
started construction and its copy
stored in animals->dog
dog destructed: some dog that constructed in Dog("layka")
started destruction
but animals->dog
is alive along with its name.
layka
animal destructed: start of Animal destructor but not its end
dog destructed: start of animals->dog
destructor
Animal not destructed before animals->dog
it simply started destructor first. Example below shows what happens in destructor of Animal:
没有在动物之前毁灭的动物->狗它只是先开始毁灭。下面的示例显示了在动物的析构函数中发生的情况:
~Animals() {
std::cout << "animal destructed\n"; //animal still exist
std::cout << "dog destructed\n";// animals.dog still exist
//destroys animals.dog.name
//destroys whole animals.dog
//animal exist but animals->dog no more
//destroys whole animal
}
更多回答
Can you clarify what you mean by "Order of output is not order of destruction"?
你能澄清一下你所说的“产出顺序不是销毁顺序”是什么意思吗?
okay but why the copy is still alive along with its name, isn't it created on the stack? I know it's part of the allocated animal object, but (I think) that isn't enough for the dog object to have its lifetime extended.
好的,但为什么副本和它的名称仍然活着,它不是在堆栈上创建的吗?我知道它是分配的动物对象的一部分,但(我认为)这还不足以延长狗对象的生命周期。
Copy of dog in animals->dog is not a reference to dog created in Dog("layka") it's totally new dog and has its own life time.
狗在动物中的复制->狗不是指狗在狗(“莱卡”)中创造的狗,它是完全新的狗,有自己的生命周期。
我是一名优秀的程序员,十分优秀!