C++11智能指针(一):shared_ptr介绍与实例

什么是std::shared_ptr<>?

std::shared_ptr<>是c++11中引入的一种智能指针,它足够聪明,如果指针不在任何地方使用,就会自动删除指针。这可以帮助我们彻底消除内存泄露和悬挂指针的问题。

shared_ptr和共享所有权

它遵循共享所有权的概念,即不同的shared_ptr对象可以与相同的指针相关联,并且在内部使用引用计数机制来实现。

每个shared_ptr对象内部指向两块内存区域
1)指向对象
2)指向用于引用计数的控制数据

共享所有权怎样在引用计数的帮助下工作
·当一个新的shared_ptr对象与一个指针相关联时,在它的构造函数中,它将与这个指针相关的引用计数增加1.
·当任何shared_ptr对象超出作用域时,则在其析构函数中将相关指针的引用计数递减1.当引用计数变为0时,意味着没有任何shared_ptr对象与这块内存关联,在这种情况下,它使用“删除”功能删除这块内存

创建shared_ptr对象

当我们将shared_ptr对象与原始指针绑定时,

std::shared_ptr<int> p1(new int());
它在堆上分配两块内存:
1)为int分配的内存
2)用于引用计数的内存,将用于管理与此内存相关的shared_ptr对象的技术,初始值为1。

检查shared_ptr对象的引用计数
p1.use_count();


std::make_shared<T>

如何分配指向shared_ptr的指针

//Compile Error
std::shared_ptr<int> p1 = new int(); //Compile error

因为采用参数的shared_ptr构造函数是Explicit,并且在上面的行中,我们正在隐含地调用它。创建shared_ptr对象的最好方法是使用 std::make_shared,

std::shared_ptr<int> p1 = std::make_shared<int>();
std::make_shared为引用计数所需的对象和数据结构做了一次内存分配,即新运算符只会被调用一次。


分离关联的原始指针
可以调用reset()方法使std::shared_ptr对象解除连接它的指针

无参数的reset()函数

p1.reset();
它将引用计数减1,如果引用计数变为0,则删除指针

有参数的reset()函数

p1.reset(new int(34));
在这种情况下,它将在内部指向新的指针,因此其引用计数将再次变为1。

使用nullptr重置

p1 = nullptr;

shared_ptr是一个伪指针
shared_ptr作为普通的指针,即我们可以在shared_ptr对象上使用*和->,也可以像其他shared_ptr对象那样进行比较;

完整的例子:

#include <iostream>
#include <memory>   //使用shared_ptr需要include它

int main() {
  //通过make_shared创建shared_ptr
  std::shared_ptr<int> p1 = std::make_shared<int>();
  *p1 = 78;
  std::cout << "p1 = " << *p1 << std::endl;

  //查看引用计数
  std::cout << "p1 Reference count = " << p1.use_count() << std::endl;

  //第二个shared_ptr也将在内部指向相同的指针
  //这将会使引用计数变为2
  std::shared_ptr<int> p2(p1);

  //查看引用计数
  std::cout << "p2 Reference count = " << p2.use_count() << std::endl;
  std::cout << "p1 Reference count = " << p1.use_count() << std::endl;

  //比较智能指针
  if (p1 == p2) {
    std::cout << "p1 and p2 are pointing to same pointer\n";
  }

  std::cout << "Reset p1" << std::endl;

  //重置shared_ptr,在这种情况下,其内部不会指向内部的任何指针
  //因此其引用计数将会变为0
  p1.reset();
  std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;

  //重置shared_ptr,在这种情况下,其内部将会指向一个新的指针
  //因此其引用计数将会变为1
  p1.reset(new int(11));
  std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;

  //分配nullptr将取消关联指针并使其指向空值
  p1 = nullptr; 
  std::cout << "p1 Reference Count = " << p1.use_count() << std::endl;

  if (!p1) {
    std::cout << "p1 is NULL" << std::endl;
  }

  return 0;
}
输出:

p1 = 78
p1 Reference count = 1
p2 Reference count = 2
p1 Reference count = 2
p1 and p2 are pointing to same pointer
Reset p1 
p1 Reference Count = 0
p1  Reference Count = 1
p1  Reference Count = 0
p1 is NULL



  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值