C++Primer :第十二章:shared_ptr和new的结合使用

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
}

我们必须将shared_ptr显式地绑定到一个想要返回的指针上:

shared_ptr<int> clone(int p){
     
	//显式用int*创建shared_ptr
	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
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初始化另一个智能指针或者为另一个指针指针赋值。

你可能感兴趣的:(C++学习笔记)