智能指针shared_ptr

        当使用new关键字分配内存时,如果不回收会导致内存泄漏,因此需要在需要使用delete来释放分配的内存。然而这很容易忘记内存释放,在delete之前throw exception也会导致内存泄露。

        智能指针是一直更为安全的动态内存使用方式,与常规执政不同的是它可以自动释放所指向的对象。常见的三个智能指针模板(auto_ptr、unique_ptr和shared_ptr)都定义了类似指针的对象,可以将 new 获得(直接或间接)的地址赋给这种对象。当智能指针过期时,其析构函数将使用delete来释放内存。

1、shared_ptr创建

        如果程序要使用多个指向同—个对象的指针,应选择 shared_ptr。shared_ptr包含在头文件memory中,并位于命名空间std中。  shared_ptr是一个模板类,在创建时需要指定类型,也可以选择指定自己的构造方法和析构方法,也可以利用已有的智能指针进行拷贝创建。

//默认初始化,没有获取任何指针的所有权,保存着一个空指针,引用计数为0
std::shared_ptr<int> p1;

//拥有指向int的指针所有权,引用计数为1
std::shared_ptr<int> p2 (new int);

//拥有指向int的指针所有权,引用计数为1,拥有自己的析构方法
std::shared_ptr<int> p3 (new int, deleter);

//拥有指向int的指针所有权,拥有自己的构造函数与析构函数,可以为成员中的指针分配内存
std::shared_ptr<int> p4 (new int, [](int* p){delete p;}, std::allocator<int>());

//拥有指向int的指针所有权
std::shared_ptr<int> p5 (p4);

//获取指向int指针所有权,并将引用计数设置为1
std::shared_ptr<int> p6 (std::unique_ptr<int>(new int));

2、赋值

          赋值有三种方式,可以通过拷贝赋值、移动,以及可以使用make_shared()一次性分配好内存。

std::shared_ptr<int> p0 = std::make_shared<int>(1)

//拷贝,引用计数二者相同
std::shared_ptr<int> p1 = p0;
cout << *p1 << endl //输出1

//移动,引用移动,后者获得前者的引用,前者引用清零
std::shared_ptr<int> p2 = p0;
cout << *p2 << endl //输出1
cout << *p0 << endl //异常

//make_shared()
std::shared_ptr<int> p3 = std::make_shared<int>(2);
cout << *p3 << endl //输出2

3、引用计数       

 std::shared_ptr内部维护一个引用计数来标识指向该资源的指针数目,一些知识点如下:

  •  std::shared_ptr的大小是原始指针的两倍,因为它的内部有一个原始指针指向资源,同时有个指针指向引用计数
  • 默认初始化引用计数为0,若初始化时通过new获取指针所有权,则引用计数为1
//默认初始化,没有获取任何指针的所有权,保存着一个空指针,引用计数为0
std::shared_ptr<int> p1;

//拥有指向int的指针所有权,引用计数为1
std::shared_ptr<int> p2 (new int);
  • 在拷贝赋值操作中, 若被拷贝者计数为0,则拷贝后被拷贝者和拷贝者引用计数均为0;若被拷贝者计数为n(n>0),则拷贝之后二者引用计数均为 n+1
std::shared_ptr<int> p1; //引用计数为0
std::shared_ptr<int> p2 (new int); //引用计数为1

std::shared_ptr<int> p3 = p1; //p1和p3引用计数为0
std::shared_ptr<int> p4 = p2; //p2和p4引用计数均为2
  • 在移动move()操作中,被转移者引用计数清零,而转移者或者被转移者的引用计数
std::shared_ptr<int> p1 = std::make_shared<int>(1); //引用计数为1

std::shared_ptr<int> p2 = std::move(p1) //p2引用计数为1,p1引用计数为0

4、常用操作与方法

4.1 p和*p

  • p :将p用作一个条件判断,若p指向一个对象,则为true
  • *p:解引用p,获得它指向的对象
std::shared_ptr<int> p1 = std::make_shared<int>(1);
std::shared_ptr<int> p2();

cout << p1 << endl;  //输出0x55555556df10
cout << p2 << endl;  //输出0

cout << *p1 << endl;  //输出1
cout << *p2 << endl;  //异常

4.2 make_shared<T>(args)

        安全的分配和使用动态内存的标准库函数,在动态内存中分配一个对象并使用args初始化,返回指向此类型为T的对象的shared_ptr,头文件在memory中。常见定义如下

std::shared_ptr<int> p1 = std::make_ptr<int>(2); // *p为2

std::shared_ptr<double> p2 = std::make_ptr<int>(2.2); // *p为2.2

std::shared_ptr<string> p3 = std::make_ptr<string>("hello world"); // *p为"hello world"

4.3 get()

        返回p中保存的指针。要小心使用,若智能指针释放了其对象,返回指针所指向的对象也会消失。

int *p = new int(2);
std::shared_ptr<int> p1(p);

cout << *p1.get() << endl;  //输出2

delete p;

cout << *p1.get() << endl;  //异常

4.4 use_count()

        获取引用计数

std::shared_ptr<int> p1;
cout << p1.use_count() <<endl //输出0

std::shared_ptr<int> p2 (new int);
cout << p2.use_count() <<endl //输出1

std::shared_ptr<int> p3(p2);
cout << p2.use_count() <<endl //输出2

4.5 swap(p, q)

        交换p和q中的指针,也可以使用p.swap(q)的方式

std::shared_ptr<int> p1 = std::make_ptr<int>(1); 
std::shared_ptr<int> p2 = std::make_ptr<int>(2);

swap(p1, p2);
cout << *p1 << endl; //输出2
cout << *p2 << endl; //输出1

p1.swap(p2);
cout << *p1 << endl; //输出1
cout << *p2 << endl; //输出2

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值