C++中的智能指针

1、什么是智能指针

智能指针是行为类似于指针的类对象。

2、为什么使用智能指针

看一下函数:

void remodel(std::string& str)
{
  std::string* ps = new std::string(str);
  ...
    str = ps;
  return;
}

可以看出代码中存在错误,分配的内存没有收回。解决的办法是在return前面加上一句:

delete ps;

但是实际工作当中难免忘记,因此智能指针就是基于这样一种思想:给予ps一个析构函数,让ps过期时自动地释放指向的内存。

3、使用智能指针

C++有四种智能指针:auto_ptr、unique_ptr、shared_ptr和weak_ptr。本文主要介绍前三种。
要创建智能指针,首先要包含头文件memory,该文件定义模版。例如,auto_ptr包含如下构造函数:

template<class X>class auto_ptr
{
public:
  explicit auto_ptr(X* p = 0)throw();
}
auto_ptr<double>pd(new double);

上述语句声明了一个指向double的智能指针。
如果将2中的普通指针用智能指针替换。如下:

void remodel(std::string& str)
{
  std::auto_ptr<std::string> ps(new std::string(str));
  ...
  str = *ps;
  return;
}

注意:
(1)智能指针模版位于命名空间std内。
(2)所有的智能指针类都有一个explicit构造函数,将指针作为参数,因此不需要自动将指针转换为智能指针。
例如:

shared_ptr<doubel>pd;
double* p=new double;
pd=p;//not allowed
pd=shared_ptr<double>(p);//allowed

4、三种智能指针的区别

智能指针在很多方面类似于常规指针:解引用(*ps)、访问结构成员(ps->data)、将它赋给常规类型的指针,但是某些情况下可能出现问题。
(1)首先用个避免一点:

string v("Hello,world!");
shared_ptr<string>pv(&v);

当pv过期时会使用delete来释放v的非堆内存,这是错误的。
(2)看下面代码:

auto_ptr<string> ps(new string("Hello,world!"));
auto_ptr<string> ps1;
ps1=ps;

如果ps和ps1为常规指针,那么ps和ps1指向同一个string对象,但是对于智能指针这是无法接受的,因为程序会释放一个对象两次。为此可以使用三种方法解决:
1)定义赋值运算符,执行深度复制,使指针指向不同的对象。
2)建立所有权概念,即对一个对象只能有一个智能指针拥有它,使用赋值操作转让所有权。auto_ptr和unique_ptr采用这个方案,但是unique_ptr的策略更严格。

auto_ptr<string> ps(new string("Hello,world!"));
auto_ptr<string> ps1;
ps1=ps;//allowed

ps1接管string对象的所有权后,ps的所有权被剥夺。这样可以防止ps和ps1的析构函数同时删除同一个对象。但是如果随后使用ps则会出现问题。
但是使用unique_ptr编译器则会报错:

unique_ptr<string> ps(new string("Hello,world!"));
unique_ptr<string> ps1;
ps1=ps;//not allowed

在将一个unique_ptr赋给另一个时,如果源unique_ptr为临时右值,编译器允许赋值;如果源unique_ptr将存在一段时间则不允许这么做。例如:

unique_ptr<string> ps(new string("Hello,world!"));
unique_ptr<string> ps1;
ps1=ps;//not allowed
ps1=unique_ptr<string>(new string("Hello,world1"));//allowed

总之,unique_ptr的安全性要比auto_ptr高。
3)创建更高智能的指针,跟踪引用特定对象的智能指针数,称为引用计数。赋值时计数加1,指针过期时计数减1,只有最后一个指针过期时才调用delete。shared_ptr采用这个方案。

5、选择智能指针

如果程序要使用多个指向同一对象的指针,应选择shared_ptr;
如果不需要多个指向同一对象的指针,则选择unique_ptr。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值