本条款主要讲了RAII(Resource Acquisition Is Initialization)资源取得实际便是初始化时机。
通过“管理对象”的构造和析构完成对对象的资源管理。
书中给出的例子:
class Investment{
//...
};
Investment* createInvestment();//返回一个指向Investment对象的指针
void f()
{
std::auto_ptrpInv(createInvestment);
//...
}
在函数f中,当栈上变量auto_ptr<>pInv
销毁时,将自动删除其所指之物,也就达到了释放资源的作用。
ps:也是由于这个原因多个auto_ptr不能指向同一个对象,并且在容器中不能使用auto_ptr..
另外还有一个例子:
假设我们对锁有一个封装:
class MutexLock : public boost::noncopyable
{
public:
MutexLock();
~MutexLock();
void lock();
void unlock();
private:
pthread_mutex_t mutex_;//互斥锁
bool isLocking_;
};
为了防止误操作导致的死锁,可以写一个管理类:
class MutexLockGuard:public boost::noncopyable
{
public:
MutexLockGuard(MutexLock &mutex):mutex_(mutex){ mutex_.lock();}//构造时加锁
~MutexLockGuard()//析构时解锁
{
mutex_.unlock();
}
private:
MutexLock &mutex_;
};
这样,我们就能轻松管理临界区,而不用担心死锁:
int count=0;
{
MutexLockGurad lock(mutex);
count++;
}//临界区
//...
//离开lock的作用域,lock作为栈上变量,自动释放,调用析构函数,同时释放锁。
一个RAII对象禁止复制,比如上述MutexLockGuard
类继承于noncopyable
MutexLockGuard lock1(mutex);
//从业务角度来说,可能造成死锁
MutexLockGuard lock2(lock2);
底层资源的引用计数就是shared_ptr
的做法,这保证当对象的引用计数降为0时,删除所指对象,这是shared_ptr
的默认行为,我们也可以为shared_ptr指定删除器,来指定当对象的引用计数为0时执行的操作。
如果要对RAII class进行拷贝,那么一定也要拷贝所管理的对象,也即深拷贝。
这对于我们并不陌生,shared_ptr
中可以通过get()访问所管理的对象的指针:
element_type* get() const noexcept;
Get pointer
Returns the stored pointer.The stored pointer points to the object the shared_ptr object >dereferences to, which is generally the same as its owned pointer.
#include
#include
int main () {
int* p = new int (10);
std::shared_ptr<int> a (p);
if (a.get()==p)
std::cout << "a and p point to the same location\n";
// three ways of accessing the same address:
std::cout << *a.get() << "\n";
std::cout << *a << "\n";
std::cout << *p << "\n";
return 0;
}
//输出:
//a and p point to the same location
//10
//10
//10
new 和 delete 一起用。
new []和delete[]一起用。
int main()
{
int *pa=new int(10);
delete pa;
int *pb=new int[10];
delete[] pb;
}
书中例子可以说明:
int priority();
void processWidget(shared_ptrpw,int priority);
假设有如上函数声明,本条款希望,传入函数processWidget的智能指针对象能够事先构造完成。
processWidget(shared_ptr(new Widget),priority());
上述调用可能发生资源泄露,原因在于priority()调用可能发生异常,在异常发生的同时,shared_ptr
可能没有完全构造。这样的话,原始对象指针可能将会遗失。
因为,要确保shared_ptr构造完成,以独立语句来完成构造。
shared_ptr pw(new Widget);
processWidget(pw,priority);