Item 13:使用对象(智能指针)来管理资源 Effective C++笔记
2015-08-26 12:11
459 查看
Item 13: Use objects to manage resources.
熟悉智能指针的人肯定不会对此觉得陌生。利用C++中对象自动析构的特性,自动地释放资源。 C++编译器并未提供自动的垃圾回收机制,因此释放资源的责任落在了开发者的头上。 我们被要求总是成对地使用
function),用来创建一个对象的实例。
上述代码确实能够在不泄漏内存的情况下很好地执行,但问题出在
但并未显式地声明这一点,因而客户有时并不知情。即使客户知道该资源需要销毁, 也可能由于流控制语句或者异常的出现而使得资源未被及时释放。
幸运的是,我们可以用对象来包装资源,并在析构函数中释放它。这样客户便不需要维护资源的内存了。
pointer)。 典型的使用场景是,资源在堆空间中存储但只在局部被使用。
关于C++中堆空间、栈空间的使用方式,可以参考:进程的地址空间:TEXT,DATA,BSS,HEAP,STACK
在
事实上,让
可以看到,使用对象来管理资源的关键在于:创建资源后立即放入资源管理对象中,并利用资源管理对象的析构函数来确保资源被释放。
资源管理对象的实现框架正是RAII原则:acquisition is initialization,用一个资源来初始化一个智能指针。指针的析构函数中释放资源。
值得注意的是,为了防止对象被多次释放,
可以创建这样的容器,但往里面添加元素(例如
此处我们引入一个引用计数(reference-counting smart pointer,RCSP)的指针
它在没有任何其他指针引用到该资源时,进行资源的释放。不同于垃圾回收器,
值得注意的是
在最新的C++标准中,智能指针已经归入
虽然智能指针有这样的问题,但C++并未提供管理数组的智能指针,因为
如果你真的需要,可以求助与Boost社区的
除非注明,本博客文章均为原创,转载请以链接形式标明本文地址: http://harttle.com/2015/08/02/effective-cpp-13.html
熟悉智能指针的人肯定不会对此觉得陌生。利用C++中对象自动析构的特性,自动地释放资源。 C++编译器并未提供自动的垃圾回收机制,因此释放资源的责任落在了开发者的头上。 我们被要求总是成对地使用
new和
delete,例如:
Investment *pInv = createInvestment(); ... delete pInv;
createInvestment这样的方法属于工厂方法(factory
function),用来创建一个对象的实例。
上述代码确实能够在不泄漏内存的情况下很好地执行,但问题出在
createInvestment()函数把释放资源的责任交给了客户,
但并未显式地声明这一点,因而客户有时并不知情。即使客户知道该资源需要销毁, 也可能由于流控制语句或者异常的出现而使得资源未被及时释放。
幸运的是,我们可以用对象来包装资源,并在析构函数中释放它。这样客户便不需要维护资源的内存了。
std::auto_ptr便是这样一个对象,它被称为智能指针(smart
pointer)。 典型的使用场景是,资源在堆空间中存储但只在局部被使用。
void f(){ std::auto_ptr<Investment> pInv(createInvestment()); }
关于C++中堆空间、栈空间的使用方式,可以参考:进程的地址空间:TEXT,DATA,BSS,HEAP,STACK
在
f()调用结束时
pInv退出作用域,析构函数被调用,最终使得资源被释放。
事实上,让
createInvestment直接返回智能指针是更好的设计。
可以看到,使用对象来管理资源的关键在于:创建资源后立即放入资源管理对象中,并利用资源管理对象的析构函数来确保资源被释放。
资源管理对象的实现框架正是RAII原则:acquisition is initialization,用一个资源来初始化一个智能指针。指针的析构函数中释放资源。
值得注意的是,为了防止对象被多次释放,
auto_ptr应当是不可复制的。 复制一个
auto_ptr会使它变成空,资源被交付给另一个只能指针。
std::auto_ptr<int> p1 (new int); *p1.get()=10; std::auto_ptr<int> p2 (p1); std::cout << "p2 points to " << *p2 << '\n'; // p2 points to 10 // (p1 is now null-pointer auto_ptr)
.get方法返回资源的指针。
auto_ptr古怪的复制行为导致它并不是管理资源的最佳方式,甚至在STL中
auto_ptr的容器也是不允许的:
可以创建这样的容器,但往里面添加元素(例如
push_back)时会导致编译错。
auto_ptr<int> p1(new int); vector<auto_ptr<int>> v; // OK,可以编译 v.push_back(p1); // 编译错!
此处我们引入一个引用计数(reference-counting smart pointer,RCSP)的指针
shared_ptr。
它在没有任何其他指针引用到该资源时,进行资源的释放。不同于垃圾回收器,
shared_ptr未能解决环状引用的问题。
值得注意的是
auto_ptr和
shared_ptr只能管理单个资源,因为它们是使用
delete而非
delete[]来实现资源释放的。常见的错误便是传递数组进去:
std::tr1::shared_ptr<int> spi(new int[1024]);
在最新的C++标准中,智能指针已经归入
std命名空间了。我们可以这样使用:
std::shared_ptr<int>。
虽然智能指针有这样的问题,但C++并未提供管理数组的智能指针,因为
vector等容器就可以很好地完成这个工作。
如果你真的需要,可以求助与Boost社区的
boost::scoped_array和
boost::shared_array。
除非注明,本博客文章均为原创,转载请以链接形式标明本文地址: http://harttle.com/2015/08/02/effective-cpp-13.html
相关文章推荐
- Item 12:完整地拷贝对象(拷贝构造函数、复制运算符) Effective C++笔记
- c++实现单链表
- 创建新线程
- 对于EnterCriticalSection和LeaveCriticalSection的理解和用法
- C语言编程中建立和解除内存映射的方法
- 设计模式C++实现(1)——工厂模式
- 几种快速傅里叶变换(FFT)的C++实现
- C++_编写动态链接库
- 深入理解C语言的函数调用过程
- c++与perl在正则表达式运算速度上的比较
- 【资料整理】C语言位运算总结
- C++多态
- WTL小问题解决方法汇总
- LeetCode 215. Kth Largest Element in an Array
- [VS2010]_[初级]_[VC++ Express 使用WDK的ATL编译出现的问题解决办法]
- [VS2010]_[初级]_[VC++ Express 使用WDK的ATL编译出现的问题解决办法]
- C语言中字符串的内存地址操作的相关函数简介
- C++中的标准库类型
- C# 中动态调用C++动态链接
- C# 中动态调用C++动态链接