1、不能用一个原始地址初始化多个共享智能指针,会导致同一内存释放多次。

class Test {
public:
    Test() {
        cout << "test的默认构造函数" << endl;
    }
    ~Test()
    {
        cout << "test的析构函数" << endl;
    }
};
void test01()
{
    Test *t = new Test;
    shared_ptr<Test>sp1(t);
    shared_ptr<Test>sp2(t);
    cout << "sp1的引用计数:" << sp1.use_count() << endl;
    cout << "sp2的引用计数:" << sp2.use_count() << endl;  
}

运行结果:

 原因分析:

在这个例子中使用同一个指针 t 构造了两个智能指针对象 sp1 和 sp2,这二者之间是没有任何关系的,因为 sp2 并不是通过 sp1 初始化得到的实例对象。在离开作用域之后 指针t将被构造的两个智能指针各自析构,导致重复析构的错误。

2、在类里面返回一个管理这当前对象指针的智能指针对象,如下写法依然出现内存重复释放,原因和上面一样。

class A
{
public:
    A()
    {
        cout << "A的默认构造" << endl;
    }
    
    shared_ptr<A> getshareptr()
    {
        return shared_ptr<A>(this);
    }
    ~A()
    {
        cout << "A的析构函数" << endl;
    }
};
void test03()
{
    
    shared_ptr<A>sp1(new A);
    shared_ptr<A>sp2 = sp1->getshareptr();
    cout << "sp1的引用计数:" << sp1.use_count() << endl;
    cout << "sp2的引用计数:" << sp2.use_count() << endl;
}

使用weak_ptr改进版。使类继承于enable_shared_from_this

class A:public enable_shared_from_this<A>
{
public:
    A()
    {
        cout << "A的默认构造" << endl;
    }
    //在类里面返回一个管理这当前对象指针的智能指针对象
    shared_ptr<A> getshareptr()
    {
        return shared_from_this();

      //在这个函数内部使用weak_ptr调用lock()来返回一个shared_ptr对象 } ~A() { cout << "A的析构函数" << endl; } }; void test03() { // enable_shared_from_this类里面的weak_ptr也被初始化 shared_ptr<A>sp1(new A); shared_ptr<A>sp2 = sp1->getshareptr(); cout << "sp1的引用计数:" << sp1.use_count() << endl; cout<<"sp2的引用计数:<<sp2.use_count()<<endl; }

 3、循环引用会导致内存泄漏。如下所示,A里面有个B类型的共享指针指针,B里面有个A类型的共享指针指针。初始化A类型的共享智能指针和B类型的共享智能指针,使A中B类型的共享指针指向B类型的共享智能指针,使B中A类型的共享指针指向A类型的共享智能指针。

 1 class BB;
 2 class AA
 3 {
 4 public:
 5     shared_ptr<BB> bsp;
 6     ~AA()
 7     {
 8         cout << "AA的析构函数" << endl;
 9     }
10 };
11 class BB
12 {
13 public:
14     shared_ptr<AA> asp;
15     ~BB()
16     {
17         cout << "BB的析构函数" << endl;
18     }
19 };
20 void test04()
21 {
22     shared_ptr<AA> ap(new AA);
23     shared_ptr<BB> bp(new BB);
24     ap->bsp = bp;
25     bp->asp = ap;
26     cout << "A的引用计数:" << ap.use_count() << endl;
27     cout << "B的引用计数:" << bp.use_count() << endl;
28    
29 }

运行结果:

 

 发现没有打印析构函数,发生了内存泄漏。

解决办法:在第5行或者第14行把shared_ptr修改位weak_ptr,例如修改第5行

weak_ptr<BB> bsp;

运行结果:

 

 这是由于bsp 是 weak_ptr 类型,打破了循环引用,这个赋值操作ap->bsp=bp并不会增加引用计数,所以 bp 的引用计数仍然为 1,在离开作用域之后 bp 的引用计数减为 0,类 B 的实例对象被析构。

在类 B 的实例对象被析构的时候,内部的 asp 也被析构,A内存的引用计数减为 1,当共享智能指针 ap 离开作用域之后,内存的引用计数减为 0,类 A 的实例对象被析构。