如果我删除课程,shared_ptr 会被删除吗

Posted

技术标签:

【中文标题】如果我删除课程,shared_ptr 会被删除吗【英文标题】:will the shared_ptr be deleted if i delete the class 【发布时间】:2015-05-31 03:18:32 【问题描述】:

我有这样的课:

标题:

class CurlAsio 
public:
    boost::shared_ptr<boost::asio::io_service> io_ptr;
    boost::shared_ptr<curl::multi> multi_ptr;
    CurlAsio();
    virtual ~CurlAsio();
    void deleteSelf();
    void someEvent();
;

Cpp:

CurlAsio::CurlAsio(int i) 
    id = boost::lexical_cast<std::string>(i);
    io_ptr = boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service());
    multi_ptr = boost::shared_ptr<curl::multi>(new curl::multi(*io_ptr));


CurlAsio::~CurlAsio() 


void CurlAsio::someEvent() 
  deleteSelf();


void CurlAsio::deleteSelf() 
    if (io_ptr) 
        io_ptr.reset();
    
    if (multi_ptr)
        multi_ptr.reset();
    if (this)
        delete this;

在运行时,会创建和删除许多 CurlAsio 类的实例。

所以我的问题是:

    即使我正在调用 shared_ptr.reset() ,是否有必要这样做? 我在运行时监控程序的虚拟内存使用情况,我预计在调用 deleteSelf() 后内存使用情况会下降,但事实并非如此。这是为什么呢?

    如果我像这样修改 deleteSelf():

    void CurlAsio::deleteSelf() 
    
        delete this;
    
    
    

这两个共享指针会发生什么?他们也会被删除吗?

【问题讨论】:

【参考方案1】:

shared_ptr 成员有自己的析构函数来减少指针对象上的引用计数,如果计数达到 0,delete 会减少它。你不需要显式调用.reset(),因为你的析构函数即将运行无论如何。

也就是说 - 你为什么还要使用shared_ptr?这些成员真的与其他对象共享吗?如果没有 - 考虑 unique_ptr 或按值存储。

至于内存 - 在您的程序终止之前,它通常不会返回到操作系统,但可供您的内存重复使用。还有许多其他关于此的堆栈溢出问题。

如果您担心内存问题,使用泄漏检测工具是个好主意。例如,在 Linux 上,valgrind 非常出色。

【讨论】:

【参考方案2】:

    如果我像这样修改 deleteSelf():

    void CurlAsio::deleteSelf() 
      delete this;
    
    

不要这样做。这是一种反模式。如果您发现自己“需要”这个,shared_from_this 是您的解决方案:

Live On Coliru

#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>

#include <iostream>
#include <vector>

struct X : boost::enable_shared_from_this<X> 
    int i = rand()%100;

    using Ptr = boost::shared_ptr<X>;
    void hold() 
        _hold = shared_from_this();
    

    void unhold()  _hold.reset(); 

    ~X() 
        std::cout << "~X: " << i << "\n";
    
  private:
    Ptr _hold;
;

int main() 
    X* raw_pointer = nullptr; // we abuse this for demo

    
        auto some_x = boost::make_shared<X>();

        // not lets addref from inside X:
        some_x->hold();

        // now we can release some_x without destroying the X pointed to:
        raw_pointer = some_x.get(); // we'll use this to demo `unhold()`

        some_x.reset(); // redundant since `some_x` is going out of scope here
    

    // only the internal `_hold` still "keeps" the X
    std::cout << "X on hold\n";

    // releasing the last one
    raw_pointer->unhold(); // now it's gone ("self-delete")

    // now `raw_pointer` is dangling (invalid)

打印例如

X on hold
~X: 83

【讨论】:

以上是关于如果我删除课程,shared_ptr 会被删除吗的主要内容,如果未能解决你的问题,请参考以下文章

如果我从我的应用中删除应用内代码,我的应用会被拒绝吗?

[C++11]共享智能指针shared_ptr指定删除器

shared_ptr的作用

如果我在应用商店上传下一个版本的 ios 应用程序,我的旧数据会被删除吗

Redis的过期数据会被立马删除吗?

如何正确使用自定义 shared_ptr 删除器?