Effective C++条款17:以独立语句将newed对象置入智能指针
创始人
2024-03-02 01:36:45
0

Effective C++条款17:以独立语句将newed对象置入智能指针(Store newed objects in smart pointers in standalone statements)

  • 条款17:以独立语句将newed对象置入智能指针
    • 1、使用对象管理资源仍然会出现资源泄漏的用法
    • 2、智能指针资源泄漏情况
    • 3、如何避免资源泄漏
    • 5、牢记
  • 总结


《Effective C++》是一本轻薄短小的高密度的“专家经验积累”。本系列就是对Effective C++进行通读:


条款17:以独立语句将newed对象置入智能指针

1、使用对象管理资源仍然会出现资源泄漏的用法

  假设我们有个函数返回处理程序的优先权,然后用另一个函数在某动态分配所得的Widget上进行某些带有优先权的处理

int priority();
//返回优先权
void processWidget(std::tr1::shared_ptr pw, int priority); //根据优先权处理对象

  我们知道 条款13的至理名言是以对象管理资源,processWidget为它需要处理的动态分配对象Widget使用了智能指针(tr1::shared_ptr)。

  现在考虑对processWidget函数的调用:

processWidget(new Widget, priority());

  这个函数调用不能通过编译,因为在tr1::shared_ptr构造函数需要一个原始指针,但该构造函数是个explicit构造函数,无法进行隐式转换,也就是不能将“new Widget”返回的原始指针直接隐式转换为processWidget需要的tr1::shared_ptr。下面的代码将会通过编译:

processWidget(std::tr1::shared_ptr(new Widget), priority());

  虽然这里我们使用了对象类管理资源,但是这个调用仍然可能出现内存泄漏。如何才能出现资源泄漏呢?

2、智能指针资源泄漏情况

  在编译器生成一个对processWidget的调用之前,它们必须对函数参数做一些检查。第二个参数只是调用了函数priority,但是第一个参数包含两部分:

  • 执行new Widget

  • 调用tr1::shared_ptr构造函数

在调用processWidget之前,编译器必须为下面的三个步骤生成代码:

  • 调用priority

  • 执行 “new Widget”

  • 调用tr1::shared_ptr构造函数。

  对于上面三个步骤的执行顺序,c++编译器被给予了很大的弹性。(这同java和c#不同,这两门语言的执行顺序固定)“new Widget”表达式必须在tr1::shared_ptr构造函数之前被调用,因为它的结果会传递给tr1::shared_ptr作为参数,但是对priority()函数的执行次序是任意的(第一个,第二个,第三个执行都可以)。如果编译器选择第二个执行(因为这样可能会生成更高效的代码),执行顺序如下:

  1. 执行 “new Widget”
  2. 调用priority
  3. 调用tr1::shared_ptr构造函数。

  试想,如果调用priority时产生异常将会发生什么?在这种情况下,从”new Widget”返回的指针会被丢失,因为它没有存入tr1::shared_ptr中,但我们的原意是使用tr1::shared_ptr来防止资源泄漏。对processWidget的调用会使资源泄漏发生,因为在资源被创建和将资源转交给资源管理对象的时间间隔内发生了异常。

3、如何避免资源泄漏

  在上面的分析中,我们可以看到在“资源创建(new)”和“资源被使用”之间如果发生了异常,那么就会造成资源泄漏。

  • 解决办法:避免这类问题就是分离语句,将“创建的对象”与“放入智能指针对象”这两个步骤合成一步完成,而不是在函数调用中完成,例如,下面的函数调用就不会产生错误:
std::tr1::shared_ptr pw(new Widget); //以单独语句存储对象
processWidget(pw, priority()); //安全调用函数

  上面这种方法之所以行得通的,是因为编译器被给予更少的余地来对语句进行重新排序。在上面的代码中,我们将“new Widget”以及对tr1::shared_ptr构造函数的调用放在一个语句中,把对priority的调用放在另一个语句中,这样就不允许编译器在”new Priority”和tr1::shared_ptr构造函数之间执行priority。

5、牢记

  • 以独立语句将newed对象存储于(置于)智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以觉察的资源泄漏。

总结

期待大家和我交流,留言或者私信,一起学习,一起进步!

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...