boost 库 内存管理 scoped_ptr scoped_array 2

scoped_ptr

scoped_ptr包装new操作符在堆上分配的动态对象,保证动态创建的对象在任何时候都可以被正确删除,scoped_ptr的所有权不能转让

1. 类摘要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<class T> class scoped_ptr // noncopyable
{
private:
T * px;
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
void operator==( scoped_ptr const& ) const;
void operator!=( scoped_ptr const& ) const;
public:
explicit scoped_ptr( T * p = 0 );
~scoped_ptr();
void reset(T * p = 0);
T & operator*() const;
T * operator->() const;
T * get() const;
void swap(scoped_ptr & b);
};

2. 操作函数

  • 构造函数接受类型为T*的指针p,创建scoped_ptr对象,并在内部保存指针参数p,p必须是一个new表达式动态分配的结果,或者是空指针(0)。当scoped_ptr生命周期结束,析构函数~scoped_ptr()会使用delete操作符自动销毁所保存的指针对象,回收资源。
  • scoped_ptr将靠白构造函数和赋值操作符声明为私有的,禁止对指针指针的复制操作,保证被它管理的指针不能被转让所有权。
  • reset()重置scoped_ptr,删除原来保存的指针,保存新的指针。reset()一般不应该被调用,因为违背了scoped_ptr一直由scoped_ptr自己自动管理的本意。
  • scoped_ptr用operator()和operator->()重载解引用操作符和箭头操作符->,模仿被代理的原始指针的行为。
  • swap()交换两个scoped_ptr保存的原始指针。
  • get()返回scoped_ptr内部保存的原始指针。

3. 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class A
{
public:
A()
{
cout<<"A ctor"<<endl;
}
~ A()
{
cout<<"A dtor"<<endl;
}

void print()
{
cout<<"A Print"<<endl;
}

};

void TestScopedPtr()
{
scoped_ptr<A> a1(new A());
cout<<a1.get()<<endl;
//scoped_ptr<A> a2 = a1; //错误
a1->print();
(*a1).print();
}

4. 和auto_ptr的比较

scoped_ptr不能作为容器的元素,因为不支持拷贝和赋值。

scoped_ptr和auto_ptr的根本区别在指针的所有权。auto_ptr被特意设计为指针的所有权是可以转移的,同一时刻只能有一个auto_ptr管理指针。scoped_ptr把拷贝构造函数和赋值函数声明为私有的,拒绝指针所有权的转让。

scoped_array

scoped_array包装new[]操作符,在堆上动态分配数组,为动态数组提供代理,保证准确释放内存。

1. 类摘要

1
2
3
4
5
6
7
8
9
10
11
12
template<class T> class shared_array
{
public:
explicit shared_array( Y * p );
~shared_array();
void reset();
T & operator[] (std::ptrdiff_t i) const;
T * get() const;
void swap(shared_array<T> & other);
private:
T * px;
};
  • 构造函数接受的指针p必须是new[]的结果;
  • 析构函数使用delete[]释放资源,而不是delete;
  • 提供operator[]操作符重载,可以像普通数组一样用下表访问元素。

2. 使用

scoped_array和scoped_ptr设计思想相同,只能在被声明的作用域内使用,不能拷贝、赋值。

3. 建议

scoped_array不能动态增长、没有迭代器支持、不能搭配STL算法,仅是纯粹的”裸”数组接口。在需要动态数组的时候使用std::vector会更好。