shared_ptr和new的结合使用
如果我们不初始化一个智能指针,它就会被初始化为一个空指针,我们可以用new返回的指针来初始化智能指针
接受指针参数的智能指针构造函数是explicit的。因此,我们不能将一个内置指针隐式转化为一个智能指针,必须使用直接初始化形式来初始化为一个智能指针
shared_ptr<int> p1 = new int(1024); //错误:必须使用直接初始化形式
shared_ptr<int> p2(new int(1024)); //正确,使用了直接初始化形式
p1的初始化隐式地要求用一个new返回的int*来创建一个shared_ptr。由于我们不能进行内置指针到智能指针的隐式转化,因此这条初始化语句是错误的。由于相同的原因,一个返回shared_ptr的函数不能在其返回语句中隐式转化一个普通的指针:
shared_ptr<int> clone(int p){
return new int(p); //错误:试图隐式转化为shared_ptr<int>
}
我们必须将shared_ptr显式地绑定到一个想要返回的指针上:
shared_ptr<int> clone(int p){
//显式用int*创建shared_ptr<int>
return shared_ptr<int>(new int(p));
}
定义和改变shared_ptr的其他方法
shared_ptr<T> p(q); //p管理内置指针q所指的对象;q必须指向new分配的内存,且能够转化为T*类型
shared_ptr<T> p(u); //p从unique_ptr u那里接管了对象的所有权,将u置空
shared_ptr<T> p(q, d); //p将使用可调用对象d来代替delete
p.reset(); //若p是唯一指向其对象的shared_ptr,reset会释放此对象
p.reset(q); //若传递了可选的参数内置指针q,会令p指向q,否则会将p置空
p.reset(q, d);
不要混合使用普通指针和智能指针
void process(shared_ptr<int> ptr){
//使用ptr
} //ptr离开作用域被销毁
int *x(new int(1024)); //危险:x是一个普通指针,而不是一个智能指针
process(x); //错误:不能将int*转化为一个shared_ptr<int>
process(shared_ptr<int>(x)); //合法:但内存会被释放
int j = *x; //未定义的,x为一个空悬指针
上面的调用中,我们将一个临时shared_ptr传递给process。当这个调用表达式结束时,这个临时对象也就被销毁了。引用计数递减为0,所指向的内存会被释放。
shared_ptr<int> x(new int(1024));
process(x); //拷贝x会递增它的引用计数,在process中引用计数值为2
int j = *x; //正确:引用计数值为1
使用一个内置指针来访问一个智能指针所负责的对象是很危险的,因为我们无法知道对象何时会被销毁。
不要使用get初始化另一个智能指针或为智能指针赋值
智能指针定义了一个名为get的函数,它返回一个内置指针,指向智能指针管理的对象。此函数为下面一种情况所设计的:我们需要向不能使用智能指针的代码传递一个内置指针。使用get返回的指针的代码不能delete此指针。
shared_ptr<int> p(new int(42)); //引用计数为1
int *q = p.get(); //正确,但不要让q所管理的内存释放
{ //新的程序块
//未定义:两个独立的shared_ptr指向相同的内存
shared_ptr<int>(q);
} //程序块结束,q被销毁,它指向的内存被释放
int foo = *p; //未定义:P指向的内存被释放了
当我们使用p时会发生未定义的行为,而且当p销毁时,这块内存会被第二次delete
get用来将指针的访问权限传递给代码,你只有在确定不会delete指针的情况下,才能使用get。特别是,永远不要get初始化另一个智能指针或者为另一个指针指针赋值。