为什么不调用析构函数?

时间:2015-06-06 19:57:29

标签: c++ c++11 destructor shared-ptr weak-ptr

#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) 并且还调用了析构函数,我该怎么办? 代码只是为了好玩而编写,没有任何应用程序背景。

3 个答案:

答案 0 :(得分:9)

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

你真的不清楚你在这里尝试做什么。您正在编写没有用例的奇怪,笨拙的代码,并想知道如何使其工作&#34;。好吧,#34;让它工作&#34;,编写非奇怪和非尴尬的代码。根据定义,这是解决方案。

答案 1 :(得分:3)

  

&#34;但事实并非如此。任何人都可以解释原因吗?&#34;

您放弃了对使用(子)表达式

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

并且永远不会在其上调用delete(或者甚至可以这样做)。

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

答案 2 :(得分:0)

  

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

在这种情况下情况并非如此,因为您动态分配 shared_ptr从不销毁weak_ptr不会破坏它所引用的shared_ptr。当您致电lock()以获取新的shared_ptr时,共享对象的use_count()会增加到2,然后当shared_ptr的{​​{1}}增加时,会减少到1超出范围,如预期的那样。但是lock()仍然是&gt; 0因为第一个use_count()仍然在堆内存中闲置。 shared_ptr本身不是引用计数,你仍然必须像任何其他类一样分配和销毁它。它只管理它共享的对象的引用计数。

  

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

完成使用后,您必须明确shared_ptr 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