如果我删除 class,shared_ptr 会被删除吗

will the shared_ptr be deleted if i delete the class

我有一个这样的 class :

Header:

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

所以我的问题是:

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

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

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

shared_ptr 成员有自己的析构函数来减少 pointee 对象的引用计数,delete 如果计数达到 0,它会减少。你不需要调用 .reset()明确地给出了你的析构函数即将 运行 无论如何。

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

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

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

  1. if i modify the deleteSelf() like this:

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

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