对象实例在销毁后仍可访问

Object instance still accessible after destruction

提问人:username 提问时间:9/10/2023 最后编辑:Some programmer dudeusername 更新时间:9/10/2023 访问量:55

问:

我有一个将 struct 作为数据成员的结构,我的问题是为什么即使在销毁后(如输出中所示)仍然可以通过分配的实例(在 ) 中创建的实例访问AnimalDogDogAnimalAnimalDog

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;
}

输出:

animal constructed
dog constructed
dog destructed
layka
animal destructed
dog destructed

还有人可以解释为什么动物在狗之前被摧毁吗?为什么它被摧毁了两次,而只建造了一次?

我没想到它被摧毁后会有同样的价值dog.name

C++ OOP 结构 析构函数

评论

1赞 Some programmer dude 9/10/2023
如果你有一个对象已经过了它的生命周期,并且已经被破坏了,你根本不应该允许你再使用该对象的代码。如果代码允许,则它具有未定义的行为
2赞 Some programmer dude 9/10/2023
话虽如此,我认为您误解了作业中发生的复制。您创建一个临时对象,它被复制到 中,然后该临时对象被销毁。副本仍然存在。animals->dog = Dog("layka")Doganimals->dog
0赞 username 9/10/2023
好吧,但是为什么副本仍然存在,它不是在堆栈上创建的吗?我知道它是已分配对象的一部分,但(我认为)这还不足以延长对象的生命周期。animaldog
0赞 Some programmer dude 9/10/2023
指向的对象具有自己的对象。只要这个对象是活的,它的嵌入对象就是活的。将临时对象复制到此对象中。由于您在堆上创建该对象,因此其所有嵌入的成员变量和对象存储在堆中。它们包含在对象本身中。animalsDogAnimalsDogDoganimals->dogAnimalsAnimals
0赞 Some programmer dude 9/10/2023
让我们再举一个例子: .现在你做到了.你会认为该值从指向的对象中消失吗?如果成员是类(对象)的实例,则实际上是一样的。struct A { int d; };A* a = new A; a->d = 5;5Aa

答:

0赞 user10 9/10/2023 #1
  1. 动物构造

  2. 狗构造:一些临时开始的构造及其副本 存储在Dog("layka")animals->dog

  3. 狗被毁:一些被建造的狗开始被破坏 但和它的名字一起活着。Dog("layka")animals->dog

  4. 莱卡

  5. animal destructed:Animal destructor 的开始,但不是它的结束

  6. 狗被毁:析构函数的开始animals->dog

动物在它只是先开始破坏器之前没有被破坏。下面的示例显示了 Animal 的析构函数中发生的情况:animals->dog

~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
    } 

评论

0赞 Ted Lyngmo 9/10/2023
你能澄清一下“输出顺序不是破坏顺序”是什么意思吗?
0赞 username 9/10/2023
好吧,但是为什么副本连同它的名字一起还活着,它不是在堆栈上创建的吗?我知道它是分配的动物对象的一部分,但(我认为)这还不足以延长狗对象的生命周期。
0赞 user10 9/10/2023
在animals->dog中复制狗不是对狗(“layka”)中创建的狗的引用,它是全新的狗,有自己的寿命。