[笔记]《Effective C++》第三章 Resource Management
条款13:Use objects to manage resources.
- 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。
- 两个常被使用的RAII classes分别是shared_ptr和auto_ptr。前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向null。
- 注意:在C++11 =中已经摒弃auto_ptr转向使用unique_ptr,后者禁止copy构造和赋值。
auto_ptr<int> ap(new int(10));
auto_ptr<int> aone(ap);
auto_ptr<int> atwo = aone;
//这样是没问题的
unique_ptr<int> up(new int(10));
unique_ptr<int> uone(up);
unique_ptr<int> utwo = up;
//上面两行会编译失败
- 把资源放进对象内,我们便可倚赖 C++的“析构函数自动调用机制”确保资源被释放。
- 智能指针,如auto_ptr, shared_ptr, unique_ptr等,其析构函数自动对其所指对象调用delete。
- “以对象管理资源”的两个关键想法:
- 获得资源后立刻放进管理对象(managing object)内。这就是大名鼎鼎的“资源取得时机便是初始化时机”(Resource Acquisition IsInitialization;RAII)。
- 管理对象(managing object)运用析构函数确保资源被释放。
- shared_ptr是“引用计数型智慧指针”(reference-counting smart pointer;RCSP),RCSP会持续追踪共有多少对象指向某笔资源,并在无人指向它时自动删除该资源。
条款14:Think carefully about copying behavior in resource-managing classes.
- 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。
- 普遍而常见的RAII class copying行为是:抑制 copying(auto_ptr,unique_ptr)、施行引用计数法(reference counting)(shared_ptr)。不过其他行为也都可能被实现。
- “当一个 RAII 对象被复制,会发生什么事?”:
- 禁止复制。条款6告诉你怎么做:将copying操作声明为private。(unique_ptr)
- 对底层资源祭出“引用计数法”(reference-count)。(shared_ptr)
- 复制底部资源。复制资源管理对象时,进行的是“深度拷贝”。
- 转移底部资源的拥有权。资源的拥有权会从被复制物转移到目标物。(auto_ptr)
条款15:Provide access to raw resources in resource-managing classes.
- APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法。
- 对原始资源的访问可能经由显式转换或隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。
- RAII classes并不是为了封装某物而存在;它们的存在是为了确保一个特殊行为——资源释放——会发生。
条款16:Use the same form in corresponding uses of new and delete.
如果你在new表达式中使用[],必须在相应的delete表达式中也使用[]。如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。
- 如果你使用 delete时加上中括号(方括号),delete便认定指针指向一个数组,否则它便认定指针指向单一对象。
条款17:Store newed objects in smart pointers in standalone statements.
以独立语句将newed对象存储于(置入)智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏。
//declarition
int priority();
void processWidget(std::shared_ptr<Widget> pw, int priority);
//错误的调用,可能会导致泄漏资源
processWidget(std::shared_ptr<Widget>(new Widget), priority());
//正确的调用,不会泄露资源
std::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
- C++编译器在核算函数中被传递的各实参时,顺序不是固定的,在上面的错误调用中,可能会先执行"new Widget",然后在调用shared_ptr之前调用priority,此时若对priority函数调用导致异常,"new Widget"返回的指针尚未被置入shared_ptr,指针遗失,此时发生资源泄露。
- 编译器对于“跨越语句的各项操作”没有重新排列的自由(只有在语句内它才拥有那个自由度)。
分类:
读书笔记
标签:
Note
, Effective C++
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!