所谓资源就是,一旦用了它,将来必须还给系统。最常见的资源是动态分配内存,另外常见的资源还有:文件描述器、互斥锁、图形界面中的字形和笔刷、数据库连接、以及网络socket.
Item 13: 以对象管理资源
该条款背后的思想在于:把资源放进对象内,我们被可以倚赖C++的“析构函数自动调用机制”确保资源被释放。
假设如下类及函数:
class Investment { ... }; //继承体系中的root class
Investment* createInvestment(); //返回指针,指向Investment继承体系内的动态分配对象。调用者有责任删除它
void f(){
Investment* pInv = createInvestment();
...
delete pInv; //释放pInv所指对象
}
乍一看函数f()似乎没有什么不妥的,在退出函数之前我们负责任地执行释放动作。可是难以预料的是,...所省略的这段代码里,可能会抛出异常,甚至是过早地执行return语句从而使控制流将不经过delete语句。虽然谨慎地编写程序可以防止这一类错误,但是我们很难保证在后续的开发中,不同人的修改可以保证这段代码不出现我们担忧的情况。许多资源被动态分配于heap内而后被用于单一区块或函数内,它们应该在控制流离开那个区块或函数时被释放。标准程序库提供的auto_ptr正是针对这种形势而设计的,用它可以避免f函数潜在的资源泄漏可能性:
void f(){
std::auto_ptr<Investment> pInv( createInvestment() );
...
} //经由auto_ptr的析构函数自动删除pInv
这个简单的例子示范“以对象管理资源”的两个关键想法:
(1)获得资源后立刻放进管理对象内。
(2)管理对象运用析构函数确保资源被释放。
由于auto_ptr被销毁时自动删除它所指之物,所以受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它。事实上,如果通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权。STL容器要求其元素发挥“正常的”复制行为,因此这些容器容不得auto_ptr。
另一种智能指针是TR1的tr1::shared_ptr,它持续追踪共有多少对象指向某笔资源,并在无人指向它时自动删除该资源。
Item 14: 在资源管理类中小心coping行为
auto_ptr和shared_ptr只适用于heap_based的资源管理,对于非heap_based的资源,我们可能需要建立自己的资源管理类。条款14、15涉及了设计这种类需要考虑的一些细节问题。首先是复制问题。当一个RAII(Resource Acquisition is Initialization)对象被复制,会发生什么事情?复制RAII对象必须一并复制它所管理的资源,所以资源的coping行为决定RAII对象的coping行为。常见的行为有:
(1)禁止复制。如果复制动作对RAII对象不合理,应该通过声明private copying操作并且不予实现。
(2)对底层资源使用“引用计数法”,即shared_ptr的做法。tr1::shared_ptr允许指定所谓的“删除器”,那是一个函数或函数对象,当引用次数为0时便被调用。
(3)复制底部资源。即所谓的深度复制。
(4)转移底部资源的拥有权,正如auto_ptr的做法。
Item 15: 在资源管理类中提供对原始资源的访问
大部分的API直接处理资源,而不是经过封装的资源管理对象。因此我们需要一个函数可将RAII对象转换为其所内含之原始资源,显式地转换或者隐式转换。
tr1::shared_ptr和auto_ptr都提供一个get成员函数,用来执行显式转换,而且也重载了指针聚会操作符(operator->和operator*)。
隐式转换由转换操作符。
Item 16: 成对使用new和delete时要采取相同形式
当你使用new(也就是通过new动态生成一个对象),有两件事情发生。第一,内存被分配出来(通过名为operator new的函数)。第二,针对此内存会有一个(或更多)构造函数被调用。当你使用delete,也有两件事发生:针对此内存会有一个(或多个)析构函数被调用,然后内存才被释放(通过名为operator delete的函数)。delete的问题在于,即将被删除的内存这内究竟有多少对象?这个问题的答案决定了有多少个析构函数必须被调用起来。
当你对着一个指针使用delete,唯一能够让delete知道内存中是不叫 存在一个“数组大小记录”的办法就是,由你来告诉它。如果你使用delete时加上[],delete便认定指针指向一个数组,否则它便认定指针指向单一对象。
Item 17: 以独立语句将new出来的对象置入智能指针
假如有以下函数:
int priority(); //计算优先权
void processWidget( std::tr1::shared_ptr<Widget> pw, int priority ); //根据优先级处理Widget
考虑下面的调用:
processWidget( std:tr1::shared_ptr<Widget>( new Widget ), priority() );
在进入processWidget函数体之前,编译器需要做三件事:
(1)调用priority
(2)执行new Widget
(3)调用tr1::shared_ptr构造函数
关于这三件事的执行顺序,我们能肯定的只有,(2)一定执行于(3)之前,但是(1)可能在(2)前(2)后还是(3)前(3)后执行并不确定,如果编译器决定以这样的顺序执行这三件事:
(2),(1),(3)
可是可是,在执行(1)即调用priority()的时候出异常了!new Widget返回的指针将遗失,也就是,在我们还没来得及把它托付给shared_ptr前,它便泄漏了,那么我们便达不到使用智能指针的初衷了。这便是“以独立语句将new出来的对象置入智能指针”的原因了。这样调用processWidget:
std::tr1::shared_ptr<Widget> pw( new Widget ); //在独立语句内把资源托付给智能指针
processWidget( pw, priority() );
这样就不怕编译器进行可能导致泄漏的重新排列了。
分享到:
相关推荐
标题中的"C++ Effective C++ Effective.STL.pdf More+Effective+Chinese.pdf"暗示了这是一组关于C++编程语言深入实践的资源,其中包含了经典书籍《Effective C++》、《More Effective C++》以及《Effective STL》的...
《Effective C++》和《More Effective C++》是两本由Scott Meyers撰写的经典C++编程指南,深受程序员喜爱。这两本书深入探讨了C++编程的最佳实践和常见陷阱,帮助开发者写出更高效、更安全的代码。以下是对这两本书...
- 复制构造函数与赋值运算符:对于含有资源管理职责的类,应当实现深拷贝逻辑。 - 移动语义:通过移动构造函数和移动赋值运算符高效地传递资源所有权。 4. **异常安全** - 异常安全级别:理解基本、强、不抛出三...
《Effective C++》和《More Effective C++》是C++编程领域中的两部经典之作,由Scott Meyers撰写。这两本书深入浅出地探讨了如何更有效地利用C++语言特性,提升代码质量和效率,是每一位C++程序员必备的参考书籍。 ...
《Effective C++》第三版由Scott Meyers所著,是一本经典的C++编程书籍。本书不仅深入探讨了C++语言的高级特性,也提出了一系列编程实践中的最佳实践和技巧。侯捷老师翻译的中文版,使更多的中文读者能够学习和掌握...
5. **RAII(Resource Acquisition Is Initialization)**:RAII是C++中的一种设计模式,用于确保资源在需要时被正确获取并在不再需要时自动释放。书中将解释如何使用RAII管理对象生命周期,尤其是与异常安全相关的...
2. **资源管理**: - 使用智能指针(如`shared_ptr`, `unique_ptr`)来自动管理动态分配的对象,避免内存泄漏。 - 了解RAII(Resource Acquisition Is Initialization)原则,资源在构造时获取,在析构时释放。 3...
《Effective C++中文第3版》是一本由Scott Meyers所著的经典著作,该书深入浅出地介绍了C++编程语言的最佳实践与设计原则。它不仅适合初学者掌握C++的核心概念,也是资深程序员提高代码质量和性能的宝典。下面,我们...
《Effective C++》和《More Effective C++》是两本由Scott Meyers撰写的经典C++编程指南,深受程序员喜爱。这些书籍深入探讨了如何利用C++语言的特性来编写更高效、更易于理解和维护的代码。以下是这两本书中涵盖的...
在《Effective C++》中,Meyers提出了55个编写高质量C++代码的实践准则,这些准则涵盖了类的设计、对象的构造与析构、资源管理、模板和STL等多个方面。例如,他强调了构造函数的重要性,指出应该为类提供一个默认...
2. **资源管理**: -RAII(Resource Acquisition Is Initialization):了解如何通过对象生命周期来管理资源,如内存、文件句柄等。 -智能指针:掌握shared_ptr、unique_ptr和weak_ptr的区别和使用场景,以及它们...
考虑到《Effective C++ 第三版》在业界的高评价和推荐程度,这本书是C++程序员提升自己技能、学习最佳实践和避免常见陷阱的宝贵资源。如果有机会获得这本书的完整内容,读者将能够更系统地学习C++并掌握其精髓。对于...
4. 性能与资源管理:讨论了如何有效地管理内存、资源获取即初始化(RAII)的原则、内存泄漏的避免以及提高程序运行效率的方法。 5. 设计与架构:提供了一系列的编程技巧和设计原则,比如接口的设计、继承与组合的权衡...
书中的知识点涵盖了核心编程技巧,例如:构造函数和析构函数的最佳实践、拷贝控制(拷贝构造函数、拷贝赋值运算符、移动构造函数和移动赋值运算符)、资源管理、内存管理等。这些技巧是编写稳定和高效C++程序的基础...
1. 尽量使每个对象都有一个所有者,利用智能指针管理资源。 2. 尽量使用const,它能帮助编译器发现潜在错误并优化代码。 3. 避免隐式类型转换,特别是避免将运算符重载设计为隐式转换。 4. 使用const成员函数表明...
根据提供的信息,“Effective C++中文第三版”这本书是C++编程领域的一本经典著作,主要目的是帮助程序员提高C++编程技巧、理解最佳实践并避免常见的陷阱。虽然给出的部分内容并没有包含具体的章节信息或具体内容,...
### More Effective C++ 简体中文版(pdf 版).pdf #### 书籍概述 《More Effective C++》是一本由 Scott Meyers 所著的经典著作,旨在帮助程序员更好地掌握 C++ 的高级特性,并有效地应用于实际编程中。本书分为多...