在effective C++经常会提到智能指针,这里对shared_ptr进行一个总结:
1 简要介绍用法
智能指针主要是用于资源管理,当申请一个资源的时候为了保证在离开控制流的时候对应资源应该得到相应的释放,这个时候如果资源对应一个类,在构造类的时候进行资源的分配(也就是书中经常提到的Resource Acquisition Is Initialization RAII),在对象离开作用域的时候调用对应的析构函数资源得到适当的释放
这里有几个智能指针得到应用:
auto_ptr: 被销毁的时候会自动删除它所指之物,所以不能让多个auto_ptr指向同一个对象,因此对于auto_ptr的对象,在调用复制构造函数和copy assignment的时候他们会变成null, 因此他并不是管理动态分配资源的利器
shared_ptr: 实现的是引用计数型的智能指针 ,可以被自由地拷贝和赋值,在任意的地方共享它,当没有代码使用(引用计数为0)它时才删除被包装的动态分配的对象。shared_ptr也可以安全地放到标准容器中,并弥补了auto_ptr因为转移语义而不能把指针作为STL容器元素的缺陷。
注意:auto+ptr和shared_ptr在析构函数中调用delete而不是delete[]操作,因此如果在定义的时候申请了一个对象数组是一个不好的情况
<span style="font-size:14px;">auto_ptr<string> aps(new string[10])
shared_ptr<int> spi(new int[10]) //<都很不好</span>
如果一定要定义数组,那么可以利用STL中vector,同时还有boost::scope_arry,boost::shared_arry calsses 可以使用
下面是shared_ptr的一些简单的使用方法:
example1:
<span style="font-size:14px;">#include <iostream>
#include <assert.h>
#include <memory>
using namespace std;
//<在RAII中提及,资源取得的时机便是初始化时机
//<将获得的资源放到一个智能指针对象中,在初始化时进行构造,没有对象引用时调用析构函数进行释放
int main()
{
shared_ptr<int> sp(new int(10)); //一个指向整数的shared_ptr
assert(sp.unique()); //现在shared_ptr是指针的唯一持有者
shared_ptr<int> sp2 = sp; //第二个shared_ptr,拷贝构造函数
assert(sp == sp2 && sp.use_count() == 2); //两个shared_ptr相等,指向同一个对象,引用计数为2
*sp2 = 100; //使用解引用操作符修改被指对象
assert(*sp == 100); //另一个shared_ptr也同时被修改
sp.reset(); //停止shared_ptr的使用
assert(!sp); //sp不再持有任何指针(空指针)
return 0;
}</span>
<span style="font-size:14px;">class shared //一个拥有shared_ptr的类
{
private:
shared_ptr<int> p; //shared_ptr成员变量
public:
shared(shared_ptr<int> p_):p(p_){} //构造函数初始化shared_ptr
void print() //输出shared_ptr的引用计数和指向的值
{ cout << "count:" << p.use_count()
<< "v =" <<*p << endl;
}
};
void print_func(shared_ptr<int> p) //使用shared_ptr作为函数参数
{
//同样输出shared_ptr的引用计数和指向的值
cout << "count:" << p.use_count()
<< " v=" <<*p << endl; }
int main()
{
shared_ptr<int> p(new int(100));
shared s1(p), s2(p); //构造两个自定义类
s1.print(); //<3,100
s2.print(); //3,100
*p = 20;
print_func(p);//4,20 修改shared_ptr所指的值,因为作为是实参进行传递多了一次拷贝给临时变量
s1.print(); //3,20
} </span>
example3:
<span style="font-size:14px;">#include <vector>
int main()
{
typedef vector<shared_ptr<int> > vs; //一个持有shared_ptr的标准容器类型
vs v(10); //声明一个拥有10个元素的容器,元素被初始化为空指针
int i = 0;
for (vs::iterator pos = v.begin(); pos != v.end(); ++pos)
{
(*pos) = make_shared<int>(++i); //使用工厂函数赋值
cout << *(*pos) << ", "; //输出值
}