[013]以对象管理资源

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

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[10]);
    ....
    std::auto_ptr<int> pIntArray(new int[1024]);
    ....
}

shared_ptr针对Array使用的错误场景

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

这是为什么呢?

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

◆总结

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

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

时间: 2024-11-09 00:02:49

[013]以对象管理资源的相关文章

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

如果我们使用一个投资行为的程序库: #include "stdafx.h" #include <iostream> #include <memory> using namespace std; class Investment { public: }; class InvestmentFactory { public: virtual Investment* createInvestment() { Investment * inV = NULL; return

Effective C++读书笔记之十三:以对象管理资源

Item 13:Use objects to manage resources 假设我们使用一个用来塑膜投资行为的程序库,其中各式各样的投资类型继承自一个root class: class Investment { ... };  //"投资类型"继承体系中的root class 进一步假设,这个程序系通过一个工厂函数(工厂函数会"返回一个base class指针,指向新生成的derived class 对象),供应我们某特定的Investment对象: Investment

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

三.资源管理       资源就是一旦你使用了它,将来不用的时候必须归还系统.C++中最常用的资源就是动态内存分配.其实,资源还有 文件描述符.互斥器.图形界面中的字形.画刷.数据库连接.socket等. 1.        以对象管理资源       void f() {     investment *plv = createInvestment();     //这里存在很多不定因素,可能造成下面语句无法执行,这就存在资源泄露的可能.     delete plv; }      这里我们

13——以对象管理资源

RAII(resource acquisition is initialization):资源获取时便是初始化时机. 不论控制流如何离开执行的区域块,其析构函数被调用,资源被释放. 为防止内存泄露使用auto_ptr或shared_ptr():auto_ptr<class> sp(new class)+shared_ptr<class> sp2(new class) 13--以对象管理资源

effective c++条款13-17 “以对象管理资源”之RAII浅析

RAII是指C++语言中的一个惯用法(idiom),它是"Resource Acquisition Is Initialization"的首字母缩写.中文可将其翻译为"资源获取就是初始化".虽然从某种程度上说这个名称并没有体现出该惯性法的本质精神,但是作为标准C++资源管理的关键技术,RAII早已在C++社群中深入人心. 使用局部对象管理资源的技术通常称为"资源获取就是初始化".这种通用技术依赖于构造函数和析构函数的性质以及它们与异常处理的交互作

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

C++相比Java等含有gc的语言来说,内存管理方面(也包括资源管理)比较令人头疼.一些初级程序员,甚至是一些经验丰富的老程序员,也会经常在资源管理上犯错.这时候就需要一个能够自动管理资源的东西(gc),但是由于C++本身没有提供,那么只有我们自己实现了. 本节我不打算直接按照<Effective C++>本节的内容进行写作,而是手动实现一个智能指针(想想还有些小激动呢^_^). 首先,我们先编写一个测试代码(先写测试代码总是一个好习惯): //test.h #pragma once #inc

条款13:以对象管理资源

首先考虑一个工厂函数 Investment * createInvestment(); void f() { Investment * pInv = createInvestment(); ... delete pInv; } 至少上面这个函数是不安全的,例如如果...里面包含return语句的话,或者说...里面包含可能会抛出异常的语句.那么就会导致申请的内存得不到释放.而下面就说明了管理对象的一般方法: void f() { std::shared_ptr<Investment>(crea

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

为防止资源泄漏,请使用RAII(Resource Acquisiton Is Initialization) 对象,它们在构造函数中获得资源并在析构函数中释放资源. 两个常被使用的RAII classes 分别是tr1::shared_ptr和auto_ptr.前者通常是较佳选择,因为其copy行为比较直观.若选择auto_ptr,复制动作会使它(被复制物)指向null.

effective c++条款13-17 “以对象管理资源”之auto_ptr源码分析

auto_ptr是当前C++标准库中提供的一种智能指针,诚然,auto_ptr有这样那样的不如人意,以至于程序员必须像使用"裸"指针那样非常小心的使用它才能保证不出错,以至于它甚至无法适用于同是标准库中的那么多的容器和一些算法,但即使如此,我们仍然不能否认这个小小的auto_ptr所蕴含的价值与理念. 这里用了Nicolai M. Josuttis(<<The C++ standard library>>作者)写的一个auto_ptr的版本,并做了少许格式上的修