为什么不调用析构函数?

Why destructor isn't invoked?

本文关键字:析构函数 调用 为什么不      更新时间:2023-10-16
#include <memory>
#include <iostream>

struct Foo {
    Foo() { std::cout << "Constructor ...n"; }
    void doSth() {std::cout << "hi" << std::endl;}
    ~Foo() { std::cout << "Destructor ...n"; }
};

int main() {

   {std::weak_ptr<Foo> jack = (*(new std::shared_ptr<Foo>(new Foo)));
    std::cout << (jack).use_count() << std::endl;
    // std::shared_ptr<Foo> ptr = jack.lock();
    // std::cout << ptr.use_count() << std::endl;
  }
}

use_count()返回值为1,因此我认为拥有该对象的最后剩余shared_ptr将被销毁,因此将调用析构函数。但事实并非如此。有人能解释一下吗?如果我想保持这样的结构:new std::shared_ptr(new Foo)还调用了析构函数,我该怎么办?代码只是为了好玩而编写的,没有任何应用程序背景。

奇怪的是,您动态地分配了shared_ptr,并且从未做过任何事情来破坏它。如果shared_ptr没有被破坏,那么它所指向的东西也不会被破坏。

我真的不清楚你在这里想做什么。你正在编写奇怪的,笨拙的代码,没有用例,想知道如何"使它工作"。好吧,为了"让它工作",编写不奇怪和不尴尬的代码。根据定义,这就是解决方案。

"但事实并非如此。有人能解释一下吗?"

您正在丢失对使用(sub)表达式

创建的指针的引用
new std::shared_ptr<Foo>(new Foo))

并且永远不要调用delete(或者甚至不能这样做)。

因此它自己的析构函数和包装类型的析构函数永远不会被调用。

use_count()返回值为1,因此我认为拥有该对象的最后剩余shared_ptr将被销毁,因此将调用析构函数。

在这种情况下是不正确的,因为您是动态分配 shared_ptr永远不会破坏它weak_ptr不会破坏它所引用的shared_ptr。当您调用lock()以获取新的shared_ptr时,共享对象的use_count()将增加到2,然后当lock()中的shared_ptr超出范围时(如预期的那样)将减少到1。但是use_count()仍然> 0,因为第一个shared_ptr仍然挂在堆内存中。shared_ptr本身没有引用计数,你仍然需要像其他类一样分配和销毁它。它仅仅管理它正在共享的对象的引用计数。

如果我想这样维护结构:new std::shared_ptr(new Foo),并调用析构函数,我应该怎么做?

你必须明确地delete shared_ptr当你完成使用:

int main()
{
    std::shared_ptr<Foo> *jill = new std::shared_ptr<Foo>(new Foo);
    {
    std::weak_ptr<Foo> jack = *jill;
    std::cout << jack.use_count() << std::endl;
    // std::shared_ptr<Foo> ptr = jack.lock();
    // std::cout << ptr.use_count() << std::endl;
    }
    delete jill;
    return 0;
}

这完全违背了shared_ptr的初衷。你需要按照它本来的用途来使用它:

int main()
{
    std::shared_ptr<Foo> jill(new Foo);
    //std::shared_ptr<Foo> jill = std::make_shared<Foo>();
    std::weak_ptr<Foo> jack = jill;
    std::cout << jack.use_count() << std::endl;
    // std::shared_ptr<Foo> ptr = jack.lock();
    // std::cout << ptr.use_count() << std::endl;
    return 0;
}