你的分享就是我们的动力 ---﹥

智能指针shared_ptr的用法

时间:2017-01-19 20:43来源:www.chengxuyuans.com 点击:

  为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer)。

  智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。

  C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使用时需添加头文件<memory>。

  shared_ptr使用引用计数,每一个shared_ptr的拷贝都指向相同的内存。每使用他一次,内部的引用技术加1,每析构一次,内部的引用计数减1,减为0时,删除所指向的堆内存。

  1. shared_ptr的基本用法
  • 初始化

  可以通过构造函数、std::make_shared<T>辅助函数和reset方法来初始化shared_ptr:

    std::shared_ptr<int> p(new int(1));

    std::shared_ptr<int> p2 = p;

    std::shared_ptr<int> p3 = std::make_shared<int>(5);

    std::shared_ptr<int> ptr;

    ptr.reset(new int(1));

    if (ptr) {

        cout << "ptr is not null";

    }

   注意,不能将一个原始指针直接赋值给一个智能指针,如下所示,原因是一个是类,一个是指针。

    std::shared_ptr<int> p4 = new int(1);// error

  当智能指针中有值的时候,调用reset会使引用计数减1.

  • 获取原始指针  
    std::shared_ptr<int> p4(new int(5));
    int *pInt = p4.get();
  • 指定删除器

  智能指针可以指定删除器,当智能指针的引用计数为0时,自动调用指定的删除器来释放内存。std::shared_ptr可以指定删除器的一个原因是其默认删除器不支持数组对象,这一点需要注意。

  2. 使用shared_ptr需要注意的问题

  但凡一些高级的用法,使用时都有不少陷阱。

  • 不要用一个原始指针初始化多个shared_ptr,原因在于,会造成二次销毁,如下所示:
        int *p5 = new int;
        std::shared_ptr<int> p6(p5);
        std::shared_ptr<int> p7(p5);// logic error
  • 不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传入。
    function(shared_ptr<int>(new int), g());
  • 禁止通过shared_from_this()返回this指针,这样做可能也会造成二次析构。
  • 避免循环引用。智能指针最大的一个陷阱是循环引用,循环引用会导致内存泄漏。解决方法是AStruct或BStruct改为weak_ptr。
struct AStruct;
struct BStruct;

struct AStruct {
    std::shared_ptr<BStruct> bPtr;
    ~AStruct() { cout << "AStruct is deleted!"<<endl; }
};

struct BStruct {
    std::shared_ptr<AStruct> APtr;
    ~BStruct() { cout << "BStruct is deleted!" << endl; }
};

void TestLoopReference()
{
    std::shared_ptr<AStruct> ap(new AStruct);
    std::shared_ptr<BStruct> bp(new BStruct);
    ap->bPtr = bp;
    bp->APtr = ap;
}

 

转载注明地址:http://www.chengxuyuans.com/code/C++/106618.html