如果删除该类,将删除shared_ptr

时间:2015-05-31 03:18:33

标签: c++ boost shared-ptr

我有一个这样的课程:

部首:

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类实例。

所以我的问题是:

  1. 即使我正在调用shared_ptr.reset(),是否有必要这样做?
  2. 我在运行时监视程序的虚拟内存使用情况,我希望在调用deleteSelf()之后内存使用率会下降,但事实并非如此。那是为什么?
  3. 如果我像这样修改deleteSelf():

    void CurlAsio::deleteSelf() {
    
        delete this;
    
    }
    
  4. 两个共享指针会发生什么?它们也会被删除吗?

2 个答案:

答案 0 :(得分:4)

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

那就是说 - 为什么你甚至使用shared_ptr?这些成员是否真的与其他对象共享?如果不是 - 请考虑unique_ptr或按值存储。

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

如果你担心记忆,使用泄漏检测工具是个好主意。例如,在Linux上,valgrind非常出色。

答案 1 :(得分:1)

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

    void CurlAsio::deleteSelf() {
      delete this;
    }
    
  2.   

不要这样做。这是一个反模式。如果您发现自己“需要”这个,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