这一节基本讲述的是将资源放进管理对象,防止忘记释放资源。

1.一般New和Delete使用场景

void fun() {
SimpleClass* pSimpleClass1 = new SimpleClass;
.... // 如果这中间发生异常返回,则delete pSimpleClass1将不会被执行,造成内存泄漏 delete pSimpleClass1;
SimpleClass* pSimpleClass2 = createSimpleClass();
.... // 如果这中间发生异常返回,则delete pSimpleClass1将不会被执行,造成内存泄漏
delete pSimpleClass2;
}

即使通过严守规约使“...”没有会产生异常的代码,或者对异常的情况进行特殊处理。但是随着代码的不断维护,“...”很容易就会被加入会产生异常的代码,而delete的处理也就很容易被忽略了。
针对这样的情况,条款13要求,以对象管理资源。

2.如果不清楚资源将以什么方式来释放,我们可以使用自动指针auto_ptr与shared_ptr来实现:

auto_ptr使用场景

void funAutoPtr() {
std::auto_ptr<SimpleClass> pSimpleClass1(new SimpleClass);
....
std::auto_ptr<SimpleClass> pSimpleClass2(createSimpleClass());
....
}

shared_ptr使用场景

void funAutoPtr_shared() {
std::tr1::shared_ptr<SimpleClass> pSimpleClass1(new SimpleClass);
....
std::tr1::shared_ptr<SimpleClass> pSimpleClass2(createSimpleClass());
....
}

两者的区别:

auto_ptr:如通过拷贝构造函数湖泊拷贝赋值操作符赋值他们,自动指针将变成NULL,而复制所得的指针将取得指针指向的资源唯一拥有权

shared_ptr:拷贝完后两者都指向同一资源

auto_ptr复制行为场景

void funAutoPtrCopy() {
std::auto_ptr<SimpleClass> pSimpleClass1(createSimpleClass); //pSimpleClass1指向createSimpleClass返回的实例
std::auto_ptr<SimpleClass> pSimpleClass2(pSimpleClass1); //现在pSimpleClass2指向实例,而pSimpleClass1被设为null
pSimpleClass1 = pSimpleClass2; //现在pSimpleClass1指向实例,而pSimpleClass2被设为null
}

shared_ptr复制行为场景

void funAutoPtrCopy_shared() {
std::tr1::shared_ptr<SimpleClass> pSimpleClass1(createSimpleClass); //pSimpleClass1指向createSimpleClass返回的实例
std::tr1::shared_ptr<SimpleClass> pSimpleClass2(pSimpleClass1); //现在pSimpleClass1和pSimpleClass2同时指向实例
pSimpleClass1 = pSimpleClass2; //同上,无任何改变
}

3.自动指针不智能的时候

auto_ptr针对Array使用的错误场景

void funAutoPtrError() {
std::auto_ptr<std::string> pStringArray(new std::string[]);
....
std::auto_ptr<int> pIntArray(new int[]);
....
}

shared_ptr针对Array使用的错误场景

void funAutoPtrError_shared() {
std::tr1::shared_ptr<std::string> pStringArray(new std::string[]);
....
std::tr1::shared_ptr<int> pIntArray(new int[]);
....
}

这是为什么呢?

因为auto_ptr与shared_ptr两者在析构函数内做的都是delete而不是delete[]操作。这就意味着动态分配得到的数组是不能完全得到释放的。

◆总结

1.为防止资源泄露,请使用RAII(Resourse Acquisition Is Initialization)"资源取得时机便是初始化时机"对象,它们在构造函数中获得资源并在析构函数中释放资源。

2.两个常用的RAII class分别是shared_ptr和auto_ptr,前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向NULL。

[Effective C++ --013]以对象管理资源的更多相关文章

  1. Effective C++(13) 用对象管理资源

    问题聚焦: 从这条准则开始,都是关于资源管理的. 资源,一旦用了它,将来必须还给系统. 本条准则,基于对象的资源管理办法,建立在C++的构造函数,析构函数和拷贝函数(拷贝构造函数和重载赋值操作符)的基 ...

  2. Effective C++ ----以对象管理资源

    以对象管理资源 通过对象的析构函数的自动调用来自动释放资源 第一部分:几种典型的以对象管理资源的例子 1. STL::auto_ptr 获取资源后立刻放入资源管理对象 std::auto_ptr< ...

  3. 《Effective C++》学习笔记条款13 以对象管理资源

    条款 13 :以对象管理资源 例:      voidf()      {           Investment *pInv = createInvestment();           ... ...

  4. Effective C++ 条款13/14 以对象管理资源 || 在资源管理类中小心拷贝行为

    三.资源管理       资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket ...

  5. effective C++ 读书笔记 条款14 以对象管理资源

    如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> us ...

  6. 以对象管理资源——C++智能指针auto_ptr简介

    auto_ptr是C++标准库提供的类模板,它可以帮助程序员自动管理用new表达式动态分配的单个对象.auto_ptr对象被初始化为指向由new表达式创建的对象,当auto_ptr对象的生命期结束时, ...

  7. EC笔记:第三部分:13、以对象管理资源

    C++相比Java等含有gc的语言来说,内存管理方面(也包括资源管理)比较令人头疼.一些初级程序员,甚至是一些经验丰富的老程序员,也会经常在资源管理上犯错.这时候就需要一个能够自动管理资源的东西(gc ...

  8. Effective C++ -----条款13:以对象管理资源

    为防止资源泄漏,请使用RAII(Resource Acquisiton Is Initialization) 对象,它们在构造函数中获得资源并在析构函数中释放资源. 两个常被使用的RAII class ...

  9. C++以对象管理资源

    先看下面一段代码: class Node {}; Node* CreateNode() { } void Solve() { Node *p=CreateNode(); //调用CreateNode函 ...

随机推荐

  1. ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)

    [题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ...

  2. Android LayoutInflater&LayoutInflaterCompat源码解析

    本文分析版本: Android API 23,v4基于 23.2.1 1 简介 实例化布局的XML文件成相应的View对象.它不能被直接使用,应该使用getLayoutInflater()或getSy ...

  3. pattern目录

    pattern目录 1.创建型模式 JDK1.5枚举Singleton    单例模式 AbstractFactory  工厂方法模式    简单工厂模式 Builder Prototype 2.结构 ...

  4. Parallel stepped for loops in .NET C# z

    ; i < ; i += ) public IEnumerable<int> SteppedIntegerList(int startIndex, int endEndex, int ...

  5. redis-3.0.0集群的安装及使用

    redis集群需要至少6个节点(偶数节点),3个主节点,3个从节点.注意:集群模式最好不要keys *查询数据. 1 下载redis,官网下载3.0.0版本,之前2.几的版本不支持集群模式.下载地址: ...

  6. Webservice、WSDL三种服务访问的方式【转】

    http://www.cnblogs.com/yongfeng/archive/2013/01/30/2883146.html 用soapUI试了下wsdl的测试,但还是不知道webService和W ...

  7. PowerShell:Linux程序员喜欢的cmd增强版

    Linux程序员有时偶尔使用Windows下的cmd工具,会被逼疯的,有些命令ls, cat, ps等已经条件反射一样使用. 但在cmd下,根本不知道该用什么命令,好在盖兹大叔照顾了此部分需求.从Vi ...

  8. DNS (二)协议

    报文字段含义: 标识字段 由客户程序设置并由服务器返回结果.客户程序通过它来确定响应与查询是否匹配. 标志字段 协商具体的通信方式和反馈通信状态随后的 4个16 bit字段说明最后 4个变长字段中包含 ...

  9. flash player 版本对照

  10. input文字方框中,字体颜色的变化 要求默认的字体颜色是灰色,当要输入字时,字体是正常的黑色

    1 <input type=text name='address' size=60 maxlength=60 style="color:gray" value="( ...