Smart_ptr称为智能指针,之所以智能是因为相对与原始指针,它的使用更安全,而使用方法与指针相同。原始的指针需要new/delete配对,而智能指针能够自动释放。
智能指针是程序员的重要武器,std::auto_ptr不能满足我们对智能指针的需求,例如,auto_ptr不能用作STL容器的元素,Boost的智能指针类填充了标准所留下来的缺口。
scoped_ptr
boost::scoped_ptr 用于确保正确删除动态分配的对象。scoped_ptr 有着与std::auto_ptr类似的特性,而最大的区别在于它不能转让所有权而auto_ptr可以。事实上,scoped_ptr永远不能被复制或被赋值!示例:
#include " boost/scoped_ptr.hpp "
#include < string >
#include < iostream >
int main()
{
{
boost::scoped_ptr<std::string> p(
new std::string("Use scoped_ptr often."));
if (p) std::cout << *p << ' ';
size_t i=p->size();
*p="Acts just like a pointer";
} // 这里p被销毁,并删除std::string
}
在函数中使用scoped_ptr, 你可以在函数中自由地return, 或抛异常。
把指针型类成员替换成scoped_ptr, 你可以在构造函数中轻松地处理异常。
如果动态对象是数组,就使用scoped_array.
shared_ptr
shared_ptr是引用计数智能指针。当引用计数降为零,没有对象再需要这个共享的对象时,这个对象就会自动销毁了。shared_ptr 可以从一个指针、或另一个shared_ptr构造。还可以传递一个删除器(deleter)参数给shared_ptr的构造函数,删除器来处理共享资源的释放,这对于管理那些不是用new分配也不是用delete释放的资源时非常有用。
#include " boost/shared_ptr.hpp "
#include < cassert >
class A
{
boost::shared_ptr<int> no_;
public:
A(boost::shared_ptr<int> no) : no_(no) {}
void value(int i) {*no_=i;}
} ;
class B
{
boost::shared_ptr<int> no_;
public:
B(boost::shared_ptr<int> no) : no_(no) {}
int value() const {return *no_;}
} ;
int main()
{
boost::shared_ptr<int> temp(new int(14));
A a(temp);
B b(temp);
a.value(28);
assert(b.value()==28);
}
将大对象的shared_ptr放入标准库容器进行管理是一个绝好的方案。因为不必承受对象复制的代价,也不必维护指针的完整性。
下面是如何把共享指针存入标准库容器的例子。
#include
"
boost/shared_ptr.hpp
"
#include < vector >
#include < iostream >
class A
{
public:
virtual void sing()=0;
protected:
virtual ~A() {};
} ;
class B : public A
{
public:
virtual void sing() {
std::cout << "Do re mi fa so la";
}
} ;
boost::shared_ptr < A > createA()
{
boost::shared_ptr<A> p(new B());
return p;
}
int main()
{
typedef std::vector<boost::shared_ptr<A> > container_type;
typedef container_type::iterator iterator;
container_type container;
for (int i=0;i<10;++i) {
container.push_back(createA());
}
std::cout << "The choir is gathered: ";
iterator end=container.end();
for (iterator it=container.begin();it!=end;++it) {
(*it)->sing();
}
}
#include < vector >
#include < iostream >
class A
{
public:
virtual void sing()=0;
protected:
virtual ~A() {};
} ;
class B : public A
{
public:
virtual void sing() {
std::cout << "Do re mi fa so la";
}
} ;
boost::shared_ptr < A > createA()
{
boost::shared_ptr<A> p(new B());
return p;
}
int main()
{
typedef std::vector<boost::shared_ptr<A> > container_type;
typedef container_type::iterator iterator;
container_type container;
for (int i=0;i<10;++i) {
container.push_back(createA());
}
std::cout << "The choir is gathered: ";
iterator end=container.end();
for (iterator it=container.begin();it!=end;++it) {
(*it)->sing();
}
}
注意上例中A的析构是保护型的,所以不可能对shared_ptr<A>::get()返回的指针调用 delete,保证了不会有意外的删除。
shared_ptr可以通过删除器来支持处理象FILE*这样的的资源释放。
int
main()
{
{
FILE* f=fopen("test.txt","r");
if (f==0) throw file_exception();
boost::shared_ptr<FILE>
my_shared_file(f, &fclose);
fseek(&*my_shared_file, 42, SEEK_SET);
}
std::cout << "By now, the FILE* has been closed! ";
}
{
{
FILE* f=fopen("test.txt","r");
if (f==0) throw file_exception();
boost::shared_ptr<FILE>
my_shared_file(f, &fclose);
fseek(&*my_shared_file, 42, SEEK_SET);
}
std::cout << "By now, the FILE* has been closed! ";
}
注意,在访问资源时,我们需要对shared_ptr使用 &* 用法, get, 或 get_pointer。(请注意最好使用 &*. 另两个选择不太清晰)。
使用shared_array可以共享数组。
摘自:Beyond the C++ Standard Library: An Introduction to Boost 中译版