C++ unique_ptr与shared_ptr析构的一点区别

struct Base
{
    Base() {
        std::cout << "Base::构造" << std::endl;
    }
    ~Base() { //非virtual
        std::cout << "Base::~析构" << std::endl;
    }
    virtual void execute() = 0;
};

class Inherit : public Base
{
public:
    Inherit() {
        std::cout << "Inherit::构造" << std::endl;
    }
    ~Inherit() { //非virtual
        std::cout << "Inherit::~析构" << std::endl;
    }
    void execute() override {
        std::cout << "Inherit::execute()" << std::endl;
    }
};

int main() {   
    std::cout << "-----原始指针-----" << std::endl;
    {
        Base* p = new Inherit();
        p->execute();
        delete p;
    }

    std::cout << "-----unique_ptr-----" << std::endl;
    {
        std::unique_ptr<Base> p = std::make_unique<Inherit>();
        p->execute();        
    }


    std::cout << "-----shared_ptr-----" << std::endl;
    {
        std::shared_ptr<Base> p = std::make_shared<Inherit>();
        p->execute();
    }

    std::cout << "-----结束-----" << std::endl;

    return 0;
}

测试环境VS2015及VS2019。 运行结果如下:

-----原始指针-----
Base::构造
Inherit::构造
Inherit::execute()
Base::~析构
-----unique_ptr-----
Base::构造
Inherit::构造
Inherit::execute()
Base::~析构
-----shared_ptr-----
Base::构造
Inherit::构造
Inherit::execute()
Inherit::~析构
Base::~析构
-----结束-----

原因是这样的:shared_ptr的构造函数是一个模板函数,shared_ptr会记住这个指针类型即你例子中的Base类型,shared_ptr析构的时候会调用delete Base的指针,而不管这个Base是否有虚的析构函数。

简言之,在share_ptr模板类型和实际类型的析构函数都会被调用到。而unique_ptr则不会去调用模板类型的析构函数。

也许你还想进一步了解为什么unique_ptr不会去调用基类的析构函数,这是因为shared_ptr和unique_ptr的实现方式不同导致的,shared_ptr中的模板参数T允许是一个incomplete type,最终是需要一个完整类型的,通过在最后删除的时候去调用这个incomplete type的析构函数来保证类型的完整性;

而unique_ptr一开始就要求这个模板类型必须是complete type,所以也就不需要去调用模板参数类型的析构函数了。

转: www.purecpp.org

发布了248 篇原创文章 · 获赞 13 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105050739