Effective C++ 小笔记:条款13-17(第三章)
2010-03-08 21:31
381 查看
常用的资源有:内存、文件描述器(file descriptor)、互斥锁(mutex locks)、图形界面中的字体和笔刷、数据库连接、以及网络sockets。这些资源一般动态创建和分配,也就是一个指针。不论哪一种资源,重要的是,当你不再使用时,必须将它还给系统。
条款13:以对象管理资源
把资源放进对象里,我们便可以依赖C++的 析构函数 自动调用机制,确保资源被释放。对象在作用域结束时,其析构函数自动对其所指资源(对象)的指针调用delete。
C++提供了2种用于管理资源的类,“智能指针” std::auto_ptr,和 “引用计数型智能指针” std::tr1::shared_ptr。它们叫做智能指针,但本质是pointer-like对象,成员变量是表征资源的指针。二者使用方法一样:
1 class Investment { ... };
2 Investment* createInvestment();
3
4 void f()
5 {
6 ...
7 std::tr1::shared_ptr<Investment> pInv1(createInvestment());
8 // pInv1 points to the object returned from createInvestment
9 std::tr1::shared_ptr<Investment> pInv2(pInv1);
// both pInv1 and pInv2 now point to the object
pInv1 = pInv2; //OK
...
}
auto_ptr不让多个auto_ptr同时指向同一个对象。如果真的那样,对象会被删除一次以上,而那会导致“未定义行为”。为了预防这个问题,auto_ptr有一个不寻常的性质: 若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权。还记得吗,STL容器要求其存储的元素具有正常的复制行为,因此这些容器容不得auto_ptr。
shared_ptr具有正常的复制行为。可存储于STL容器。
两者在析构函数内都对资源指针执行delete,而不是delete[]。所以动态分配的数组用它们管理是个馊主意。vector和string几乎总是可以取代动态分配得到的数组。
两者有一个共同的名字,RAII对象。为防止资源泄露,请使用RAII对象。它们在构造函数中获得资源,并在析构函数中释放资源。通常,我们选择shared_ptr,因为其复制行为正常、直观。而auto_ptr复制动作会使他指向NULL。
两外,tr1::shared_ptr 允许当智能指针被建立起来时制定一个资源释放函数(所谓删除器,"deleter")绑定于智能指针身上(auto_ptr 就没有这个能耐)。当引用次数为0时候,删除器 被调用。
tr1::shared_ptr 支持定制型删除器。可以被用于自动解除互斥锁(mutexes, 见条款14)等等。
条款17:以独立语句将newed 对象置入智能指针
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); //非独立语句
std::tr1::shared_ptr<Widget> pw(new Widget); //独立语句
processWidget(pw, priority());
1行中,编译器要执行三个操作。其中两个参数的计算次序编译器先做什么是有弹性的。如果如果priority函数在new之后执行,并且函数出现异常,新生成的Widget对象将未置入智能指针,资源产生泄漏。2、3行则解决了这个问题。
条款13:以对象管理资源
把资源放进对象里,我们便可以依赖C++的 析构函数 自动调用机制,确保资源被释放。对象在作用域结束时,其析构函数自动对其所指资源(对象)的指针调用delete。
C++提供了2种用于管理资源的类,“智能指针” std::auto_ptr,和 “引用计数型智能指针” std::tr1::shared_ptr。它们叫做智能指针,但本质是pointer-like对象,成员变量是表征资源的指针。二者使用方法一样:
1 class Investment { ... };
2 Investment* createInvestment();
3
4 void f()
5 {
6 ...
7 std::tr1::shared_ptr<Investment> pInv1(createInvestment());
8 // pInv1 points to the object returned from createInvestment
9 std::tr1::shared_ptr<Investment> pInv2(pInv1);
// both pInv1 and pInv2 now point to the object
pInv1 = pInv2; //OK
...
}
auto_ptr不让多个auto_ptr同时指向同一个对象。如果真的那样,对象会被删除一次以上,而那会导致“未定义行为”。为了预防这个问题,auto_ptr有一个不寻常的性质: 若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权。还记得吗,STL容器要求其存储的元素具有正常的复制行为,因此这些容器容不得auto_ptr。
shared_ptr具有正常的复制行为。可存储于STL容器。
两者在析构函数内都对资源指针执行delete,而不是delete[]。所以动态分配的数组用它们管理是个馊主意。vector和string几乎总是可以取代动态分配得到的数组。
两者有一个共同的名字,RAII对象。为防止资源泄露,请使用RAII对象。它们在构造函数中获得资源,并在析构函数中释放资源。通常,我们选择shared_ptr,因为其复制行为正常、直观。而auto_ptr复制动作会使他指向NULL。
两外,tr1::shared_ptr 允许当智能指针被建立起来时制定一个资源释放函数(所谓删除器,"deleter")绑定于智能指针身上(auto_ptr 就没有这个能耐)。当引用次数为0时候,删除器 被调用。
tr1::shared_ptr 支持定制型删除器。可以被用于自动解除互斥锁(mutexes, 见条款14)等等。
条款17:以独立语句将newed 对象置入智能指针
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); //非独立语句
std::tr1::shared_ptr<Widget> pw(new Widget); //独立语句
processWidget(pw, priority());
1行中,编译器要执行三个操作。其中两个参数的计算次序编译器先做什么是有弹性的。如果如果priority函数在new之后执行,并且函数出现异常,新生成的Widget对象将未置入智能指针,资源产生泄漏。2、3行则解决了这个问题。
相关文章推荐
- effective c++ 笔记 (13-17)
- effective c++ 笔记 (13-17)
- Effective C++_笔记_条款13_以对象管理资源
- 《Effective C++》笔记:Tips13-Tips17
- 《Effective C++ 3》03 资源管理 条款:13-17
- 【Effective C++】读书笔记 条款13~条款17
- Effective C++(条款13-17)
- effective C++ 条款13 to 条款17
- Effective C++ 条款13学习笔记:以对象管理资源
- Effective STL学习笔记-条款13|14
- effective C++ 读书笔记 条款17 以独立语句讲newed对象置入智能指针
- 《Effective C++ 》学习笔记-第六章 条款33:避免遮掩继承而来的名称 Avoid hiding inherited names
- Effective c++学习笔记——条款09:绝不在构造和析构过程中调用virtual函数
- Effective C++ 条款17 以独立语句将newed对象置入智能指针
- effective C++笔记之条款13: 初始化列表中成员列出的顺序和它们在类中声明的顺序相同
- Effective C++_笔记_条款02_尽量以const、enum、inline替换#define
- Effective C++ 条款15学习笔记:在资源管理类型中提供对原始资源的访问
- Effective C++学习笔记 条款07:为多态基类声明virtual析构函数
- 【Effective STL】条款13-18学习笔记
- Effective C++ 阅读笔记_条款27 尽量少做转型动作