从对象调用的方法可以删除对象吗?

问题描述 投票:0回答:1

我在试图理解这里发生的事情时有点困惑。 如果一个类对象调用一个方法,然后在 tern 中销毁该对象,那么该方法不应该返回并且应该立即销毁该对象并立即调用析构函数。对吗?但是代码只是崩溃了。那么对象是否不允许调用方法来删除自身?我假设从调用堆栈的工作方式来看,指向对象的指针将被销毁,因此当函数返回给调用者时,指针在进一步向下调用调用堆栈时不再有效?

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

Foo* f = nullptr;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    delete f;
}
int main()
{
    f = new Bar();
    f->Run();
    return 0;
}

然后,当我使用 shared_ptr 运行代码时,行为似乎发生了变化,但在这种情况下,析构函数在打印“我们从回调中回来”之前被调用,代码运行但那是未定义的行为吗?

class Foo
{
public:
    virtual void Run()
    {
        printf("Entering callback\n");
        RunSomeCallback();
        printf("We're back from callback\n");
    }
    virtual void RunSomeCallback() = 0;
    
    virtual ~Foo()
    {
        printf("We're Destroyed\n");
    }
};

std::shared_ptr<Foo> f;

void DestroyFoo();

class Bar : public Foo
{
public:
    virtual void RunSomeCallback()
    {
        printf("Inside callback\n");
        DestroyFoo();
    }
};


void DestroyFoo()
{
    printf("Deleting foo\n");
    f = nullptr;
}
int main()
{
    f = std::make_shared<Bar>();
    f->Run();
    return 0;
}

打印顺序

Entering callback
Inside callback
Deleting foo
We're Destroyed
We're back from callback

那么这个对象是不是在它的所有方法都完成之前才真正被销毁?

c++
1个回答
3
投票

在成员函数仍在其上执行时对象被销毁没有问题(无论在调用堆栈中的何处)。

但是,在对象的生命周期结束并从

delete
调用析构函数后,任何函数,甚至仍在运行的成员函数,都不能访问对象的任何成员,并且对象使用的内存可以被重用其他物体也是如此。

在您的示例代码中,在调用

delete
(包括析构函数)后没有成员被访问,因此程序已定义行为并且您给出的输出是预期的。析构函数由
delete
调用,结束对象的生命周期,然后
Foo::Run
继续执行而不再接触对象。

两个代码片段都是如此。将

std::shared_ptr
设置为
nullptr
实际上也只是
delete
ing 对象。


如果这导致您的系统崩溃,那么我怀疑是编译器错误

© www.soinside.com 2019 - 2024. All rights reserved.