背景:
1998年修订的第一版C++标准只提供了一种智能指针: std::auto_ptr
。 它基本上就像是个普通的指针: 通过地址来访问一个动态分配的对象。 std::auto_ptr
之所以被看作是智能指针,是因为它会在析构的时候调用 delete
操作符来自动释放所包含的对象。 当然这要求在初始化的时候,传给它一个由 new
操作符返回的对象的地址。 既然 std::auto_ptr
的析构函数会调用 delete
操作符,它所包含的对象的内存会确保释放掉。 这是智能指针的一个优点。
当和异常联系起来时这就更加重要了:没有 std::auto_ptr
这样的智能指针,每一个动态分配内存的函数都需要捕捉所有可能的异常,以确保在异常传递给函数的调用者之前将内存释放掉。 Boost C++ 库Smart Pointers 提供了许多可以用在各种场合的智能指针。其中shared_ptr非常有价值,非常重要,非常有用。
boost库中shared_ptr:
在 Boost C++ 库中 boost::shared_ptr
,定义在 boost/shared_ptr.hpp
里。
shared_ptr与scoped_ptr一样包装了new操作符在堆上分配的动态对象,但它实现的是引用计数型的智能指针,可以被自由地拷贝和赋值,在任意的地方共享它。当没有代码使用(引用计数为0)它才删除被包装的动态分配的对象。shared_ptr也可以被安全的放到标准容器中,并弥补了auto_ptr因为转移语义而不能把指针作为STL容器元素的缺陷。
shared_ptr有两个专门的函数来检查引用计数,unique()和use_count()
boost库中的指针容器:
当需要管理动态分配的对象和数组时,最容易想到的是将这些对象存储在容器里使用 boost::shared_ptr
和 boost::shared_array
这就相当简单了。如下:
#include <boost/shared_ptr.hpp>
#include <vector>
int main()
{
std::vector<boost::shared_ptr<int> > v;
v.push_back(boost::shared_ptr<int>(new int(1)));
v.push_back(boost::shared_ptr<int>(new int(2)));
}
上面例子中的代码当然是正确的,智能指针确实可以这样用,然而因为某些原因,实际情况中并不这么用。 第一,反复声明 boost::shared_ptr
需要更多的输入。 其次,将 boost::shared_ptr
拷进,拷出,或者在容器内部做拷贝,需要频繁的增加或者减少内部引用计数,这肯定效率不高。 由于这些原因,Boost C++ 库提供了指针容器专门用来管理动态分配的对象。
#include <boost/ptr_container/ptr_vector.hpp>
int main()
{
boost::ptr_vector<int> v;
v.push_back(new int(1));
v.push_back(new int(2));
}
boost::ptr_vector
类的定义在 boost/ptr_container/ptr_vector.hpp
里,它跟前一个例子中用 boost::shared_ptr
模板参数来初始化的容器具有相同的工作方式。 boost::ptr_vector
专门用于动态分配的对象,它使用起来更容易也更高效。 boost::ptr_vector
独占它所包含的对象,因而容器之外的共享指针不能共享所有权,这跟 std::vector<boost::shared_ptr<int> >
相反。
除了 boost::ptr_vector
之外,专门用于管理动态分配对象的容器还包括:boost::ptr_deque
, boost::ptr_list
, boost::ptr_set
, boost::ptr_map
, boost::ptr_unordered_set
和 boost::ptr_unordered_map
。这些容器等价于C++标准里提供的那些。最后两个容器对应于std::unordered_set
和 std::unordered_map
,它们作为技术报告1的一部分加入 C++ 标准。 如果所使用的 C++ 标准实现不支持技术报告1的话,还可以使用 Boost C++ 库里实现的 boost::unordered_set
和 boost::unordered_map
。