[笔记]《Effective C++》第三章 Resource Management

条款13:Use objects to manage resources.

  1. 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源
  2. 两个常被使用的RAII classes分别是shared_ptrauto_ptr。前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向null。
  3. 注意:在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.

  1. 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为
  2. 普遍而常见的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.

  1. APIs往往要求访问原始资源(raw resources),所以每一个RAII class应该提供一个“取得其所管理之资源”的办法。
  2. 对原始资源的访问可能经由显式转换隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便
  • 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,指针遗失,此时发生资源泄露。
  • 编译器对于“跨越语句的各项操作”没有重新排列的自由(只有在语句内它才拥有那个自由度)。
posted @   浮生的刹那  阅读(39)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
  1. 1 Night City r e l,Artemis Delta
  2. 2 Gold Steps(人生何处不青山) Neck Deep
  3. 3 Devil Trigger Ali Edwards
  4. 4 Hopeless Case Roam
  5. 5 On My Own Blitz Kids
  6. 6 I Really Want to Stay At Your House Rosa Walton & Hallie Coggins
  7. 7 Major Crimes Health & Window Weather
Night City - r e l,Artemis Delta
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示