std::make_shared和new初始化智能指针的区别

先看代码:

class Base
{
    public:
        Base(int num):a(num) {std::cout << "Base() construct" << std::endl;}
        ~Base() {std::cout << "Base() deconstruct" << std::endl;}
        int Get() {return a;}
        
    private:
        int a;
};

void testc()
{
        std::cout << "******************************" << std::endl;
        std::cout << "******************************" << std::endl;
        
        Base *p;
        {
            std::weak_ptr gw;
            {
                auto sp = std::make_shared(42);
                gw = sp;
                p = sp.get();
            }
            std::cout << "shared_ptr release, p->a = " << p->Get() << std::endl;
        }
        std::cout << "weak_ptr release, p->a = " << p->Get() << std::endl;
}

void testd()
{
        std::cout << "==================================" << std::endl;

        
        Base *p;
        {
            std::weak_ptr gw;
            {
                std::shared_ptr sp(new Base(42));
                gw = sp;
                p = sp.get();
            }
            std::cout << "shared_ptr release, p->a = " << p->Get() << std::endl;
        }
        std::cout << "weak_ptr release, p->a = " << p->Get() << std::endl;
}

执行结果如下:

std::make_shared和new初始化智能指针的区别_第1张图片

在testc()中,只有weak_ptr生命周期也结束后,Base对象内存才真正被回收,虽然Base在shared_ptr生命周期结束后就执行了析构函数,但对象所占用的内存还未被马上回收。

而在testd()中,由于使用了new分配对象内存,Base对象内存和智能指针控制块内存不在一起,所以当shared_ptr生命周期结束后就释放了Base对象所占内存。

结论:

1、make_shared只分配一次内存,智能指针控制块和管理的对象存在同一块内存里。new初始化智能指针需要调用两次内存分配,一次给控制块分配内存,一次给对象分配内存。

2、异常安全性。当在函数的实参里初始化智能指针,使用new初始化有发生异常安全性的风险,如 function_a(std::shared_ptr ptr1(new int(100)), function_b()); 编译器可能产生代码: 1先new对象,2再执行函数function_b,3最后将new对象的指针赋给智能指针,如果第2步 function_b发生异常退出,将导致内存泄漏。

3、对象内存被延迟回收:当使用了弱指针weak_ptr引用shared_ptr时,使用make_shared初始化因为控制块和对象都在同一块内存里,虽然管理的对象已经执行析构函数,但由于weak_ptr没有释放,导致内存生命周期被意外延长,只有weak_ptr生命周期结束后,整块内存才一起被回收

你可能感兴趣的:(C++,c++,开发语言)