C++的优秀特性6:智能指针
(转载请注明原创于潘多拉盒子)
智能指针(Smart Pointer)是C++非常重要的特性。考虑如下一段使用简单指针(Plain Pointer)的代码:
A* a = new A();
B* b = new B();
......
if (condition1)
{
// return之前必须delete所有new出来的对象
delete a;
delete b;
return true;
}
......
if (condition2)
{
// return之前必须delete所有new出来的对象
delete a;
delete b;
return true;
}
.......
if (condition3)
{
// throw 之前必须delete所有new出来的对象
delete a;
delete b;
throw std::exception("bad condition3");
} // 有异常必须catch,在rethrow之前delete所有new出来的对象
try
{
......
}
catch (...) // 三个点“...”用于此处捕捉所有异常
{
delete a;
delete b;
throw; // rethrow
}
这种方式非常繁琐,也很容易犯错误(error-prone)。有没有一种方法,能管理new出来的对象,并且在return/throw/异常发生的时候自动释放这些对象呢?按照《C++的优秀特性3:构造函数和析构函数》的介绍,有一种借助构造函数和析构函数实现的模版类,可以实现这样的功能。这就是智能指针。比如标准库STL中实现了一种智能指针std::auto_ptr。有了这种智能指针,前面的程序就简单了:
std::auto_ptr<A> a(new A());
std::auto_ptr<B> b(new B());
......
a->foo(); // 像普通指针一样使用
(*b).bar(); // 像普通指针一样使用
if (condition1)
{
// return之前无需delete所有new出来的对象
return true;
}
......
if (condition2)
{
// return之前无需delete所有new出来的对象
return true;
}
.......
if (condition3)
{
// throw 之前无需delete所有new出来的对象
throw std::exception("bad condition3");
} // 有异常不处理的时候也不用catch和rethrow了
一个智能指针指向一个对象叫做这个指针持有这个对象,也就是指针是这个对象的持有者。持有者负责在适当的时机释放持有的对象。常用的智能指针有3种:
- 单持有者,e.g. std::auto_ptr。单持有者保证每个new出来的对象只有一个持有者,单这种持有关系可以转移,转移之后原持有者不再持有对象。
- 局部持有者,e.g. boost::scoped_ptr。类似单持有者,单持有关系无法转移。这决定了这种持有关系不可能脱离当前的作用域(scope),因此得名。
- 共享持有者,e.g. boost::shared_ptr。一个对象可以被一个或多个这样的共享持有者持有,持有关系可以转移,转移之后原持有者继续持有该对象,直到原持有者被析构。当一个对象的最后一个持有者析构时,持有的对象被析构。
在实际中,由于#1(单持有者)的持有关系可以转移,常常是造成麻烦,而应用场景跟#2(局部持有者)又很接近,因此Google C++规范中禁止使用auto_ptr,而建议使用scoped_ptr。共享持有者是很常用的,基本上适用于大多数的简单指针应用的情况。但是,由于shared_ptr是为共享持有关系设计的,因此为了和scoped_ptr区分,在scoped_ptr适用的场景中,不要适用shared_ptr。
实际中常见的一种错误是,智能指针持有了不该持有的对象。比如:
std::string name = "ZHANG San";
std::auto_ptr<std::string> nameHolder(&name); // 持有了不是new出来的对象,会导致segmentation fault
这其实是一种混用持有关系的问题。这可以简单的归纳为以下几种情况:
- 直接定义在栈上或data区的变量,不需要delete的。
- new出来的对象(在堆上),但程序员自己delete的。
- 不同类型的智能指针持有的对象。
这几种持有情况互相不能混用,否则会segmentation fault。
C++的优秀特性6:智能指针的更多相关文章
- C++11 新特性之智能指针(shared_ptr, unique_ptr, weak_ptr)
这是C++11新特性介绍的第五部分,涉及到智能指针的相关内容(shared_ptr, unique_ptr, weak_ptr). shared_ptr shared_ptr 基本用法 shared_ ...
- C++的优秀特性4:指针
(转载请注明原创于潘多拉盒子) 其实指针不是C++的特性,而是地地道道的C的特性.有人说C++继承了C的指针,实在是败笔,造成内存泄漏云云,纯粹是不懂.可以这么说,如果没有指针,C++会逊色很多,应用 ...
- C++新特性---智能指针
智能指针: 为什么需要智能指针? 1. malloc出来的空间,没有进行释放,存在内存泄漏的问题. 2. 异常安全问题.如果在malloc和free之间如果存 ...
- 利用模板和C++11特性实现的智能指针-作用同share_ptr
根据C++11特性实现,基本上实现了同SharePtr同样的功能,有时间继续优化.之前一直以为引用计数是一个静态的int类型,实际上静态值是不可以的.之前项目中总是不太习惯使用智能指针.通过自实现的方 ...
- 【C++11新特性】 C++11智能指针之weak_ptr
如题,我们今天要讲的是C++11引入的三种智能指针中的最后一个:weak_ptr.在学习weak_ptr之前最好对shared_ptr有所了解.如果你还不知道shared_ptr是何物,可以看看我的另 ...
- C++11特性 - Smart Pointers 智能指针
已经有成千上万的文章讨论这个问题了,所以我只想说:现在能使用的,带引用计数,并且能自动释放内存的智能指针包括以下几种: unique_ptr: 如果内存资源的所有权不需要共享,就应当使 ...
- 智能指针 - 现代C++新特性总结
C++98中的智能指针通过一个模板类auto_ptr来实现,new操作符返回的指针可以交由它来管理,程序员不用再显式的调用delete,这在一定程度上避免了堆内存忘记释放的问题:不过auto_ptr有 ...
- 智能指针shared_ptr新特性shared_from_this及weak_ptr
enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...
- [C++11新特性] 智能指针详解
动态内存的使用很容易出问题,因为确保在正确的时间释放内存是极为困难的.有时我们会忘记释放内存产生内存泄漏,有时提前释放了内存,再使用指针去引用内存就会报错. 为了更容易(同时也更安全)地使用动态内存, ...
随机推荐
- MySQL基础之第14章 存储过程和函数
避免编写重复的语句 安全性可控 执行效率高 14.1.创建存储过程和函数 14.1.1.创建存储过程 CREATE PROCEDUREsp_name ([proc_parameter[,...]]) ...
- 利用命令控制台cmd进入某个硬盘的某个文件夹的命令是什么?
在命令行窗口中输入F:后回车就可以切换到F盘,如果想查看F盘的内容,可以再输入dir后回车 (输入“F”后要再输入一个“ :”再回车才行哦)
- c# 读取IntPtr 中的数据 z
c++的写法是这样的: LRESULT CPictureQueryDlg::OnQueryPicNty(WPARAM wp, LPARAM lp) { EnableWindow(TRUE); BYTE ...
- call Kernelized Correlation Filters Tracker(Matab) in Qt(c++)
recently, i need call the KCF tracker in my graduation project. the KCF tracker is fast and best per ...
- 代码所见所得方式发布.xml
pre{ line-height:1; color:#b836b3; background-color:#000000; font-size:16px;}.sysFunc{color:#19ef0b; ...
- 【LeetCode】58 - Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...
- java类与对象的动手动脑和其他小问题
在Java中,我们可以通过组合一私有字段和一对get/set方法来定义一个属性.私有的变量,共有的方法. package sample; /** * 自定义Java类的示例 */ class MyCl ...
- kali2 vmtools
root@kali:~# cat /etc/apt/sources.list# Regular Repositoriesdeb http://http.kali.org/kali sana main ...
- Maven安装与全局profile配置
Maven 3.2 需要 JDK 1.6, Maven 3.0/3.1 需要 JDK 1.5 · 解压. · 环境变量 M2_HOME · M2 = %M2_HOME%\bin 同时也添加到PATH ...
- dom 优酷得弹出
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...