首页 > 代码库 > 《Effective C++》 读书笔记之三 资源管理

《Effective C++》 读书笔记之三 资源管理

《Effective C++》 读书笔记之三 资源管理

准备知识:

  1. 所谓资源就是,一旦用了它,将来必须还给系统。最常用的资源是动态分配内存,其他常见的资源有文件描述器、互斥锁、图形界面的字形和笔刷、数据库连接以及网络sockets。

  2. auto_ptr 是个“类指针对象”,就是所谓的智能指针,其析构函数自动对其所指对象调用delete。auto_ptr位于 #include <memory> 头文件。由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr指向同一个对象。auto_ptr有个不寻常的性质:若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权。auto_ptr并非管理动态分配资源的神兵利器。

  3. Reference-counting smart pointer(引用计数型智慧指针RCSP)是auto_ptr的一种替代方案。持续追踪共有多少对象指向某笔资源,并在无人指向它时自动删除。RCSPs提供的行为类似垃圾回收,不同的是,RCSPs无法打破环状引用(例如两个其实已经没有被使用的对象彼此互指,因而好像还处于“被使用”状态)。

  4. TR1的tr1::shared_ptr 是一个RCSP。

  5. auto_ptr和tr1::shared_ptr两者都在其析构函数内做delete而不是delete[]动作。那意味着动态分配而得的array身上使用auto_ptr或tr1::shared_ptr是不明智的。但是这是可以通过编译的。

//准备知识2auto_ptr不寻常的性质

std::auto_ptr<Investment> pInv(createInvestment());
//pInv指向createInvestment()返回物
std::auto_ptr<Investment> pInv2(pInv);
//现在pInv2指向对象,pInv被置为null
pInv = pInv2;
//现在pInv指向对象,pInv2被置为null


正文


条款13:以对象管理资源 Use objects to manage resource

获取资源后立刻放进管理对象内。(资源取得时机便是初始化时机。Resource Acquisition Is Initialization;简称RAII)

管理对象运用析构函数确保资源被释放。

例子如下:

class Investment{...};
Investment* createInvestment();

void f()//auto_ptr版本
{
	std::auto_ptr<Investment> pInv(createInvestment());
	// 调用factory函数,使用pInv经由auto_ptr的析构函数自动删除pInv
	...
}


void f()//shared_ptr版本
{
	...
	std::tr1::shard_ptr<Investment> pInv(createInvestment());
	//pInv指向createInvestment()返回物
	std::tr1::shard_ptr<Investment> pInv2(pInv);
	//现在pInv,pInv2指向同一对象
	pInv = pInv2;
	//无任何改变
	...
}

重点:

  1. 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。

  2. 两个常用的RAII classes 分布式tr1::shared_ptr 和auto_ptr。前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它指向null。

2016-11-03 22:23:43


条款14:在资源管理类中小心copying行为。

当一个RAII对象被复制,有如下几种可能

  1. 禁止复制。

    class Lock:private Uncopyable{ };

  2. 对底层资源祭出“引用计数法”。有时候我们希望保有资源,直到它的最后一个使用者被销毁。这种情况下复制RAII对象时,应该将资源的“被引用数”递增。tr1::shared_ptr便是如此。tr1::shared_ptr允许指定所谓的“删除器”,那是一个函数或函数对象,当引用次数为0时便被调用。删除器对tr1::shared_ptr构造函数而言是可有可无的第二参数。

  3. 复制底部资源。进行深度拷贝。

  4. 转移底部资源的拥有权。采用auto_ptr。

class Lock{
public:
    //以某个Mutex初始化shared_ptr,并以unlock函数作为删除器
    explicit Lock(Mutex *pm):mutexPtr(pm,unlock)
    {
        lock(mutexPtr.get());
    }
private:
    std::tr1::shared_ptr<Mutex> mutexPtr;
}

重点:

  1. 复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。

  2. 普通而常见的RAII class copying行为是:抑制copying、施行引用计数法。不过其他行为也都可能被实现。

2016-11-03 23:59:30

本文出自 “做最好的自己” 博客,请务必保留此出处http://qiaopeng688.blog.51cto.com/3572484/1869161

《Effective C++》 读书笔记之三 资源管理