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

news/2024/7/9 19:46:03

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初始化另一个智能指针或者为另一个指针指针赋值。


http://www.niftyadmin.cn/n/1773835.html

相关文章

如何打通CMDB,实现就近访问

2019独角兽企业重金招聘Python工程师标准>>> CMDB在企业中&#xff0c;一般用于存放与机器设备、应用、服务等相关的元数据。当企业的机器及应用达到一定规模后就需要这样一个系统来存储和管理它们的元数据。有一些广泛使用的属性&#xff0c;例如机器的IP、主机名、…

MBR、主分区、扩展分区、逻辑分区、活动分区、系统分区、启动分区讲解

什么是MBR和主引导引导扇区&#xff1f;什么是主分区、扩展分区、逻辑分区&#xff1f;什么是活动分区、引导分区、系统分区、启动分区&#xff1f;一下子罗列这么多概念&#xff0c;恐怕很多人都搞不清它们的区别和联系吧。网上虽然不少解释&#xff0c;但很多是模棱两可甚至是…

C++Primer : 第十二章 :智能指针和异常

智能指针和异常 即时程序块过早结束&#xff0c;智能指针类也能确保在内存不再需要时将其释放 void f(){shared_ptr<int> sp(new int(42)); //分配一个新对象//这段代码抛出一个异常&#xff0c;且在f中未被捕获 } //在函数结束时shared_ptr自动释放内存与之对应的&…

贵阳市民营经济服务平台正式上线

图为新闻发布会现场。 图为新闻发布会现场。 中新网贵阳1月14日电 (记者 张伟)贵阳市民营经济服务平台“贵商易”14日正式上线运营&#xff0c;该平台是贵阳官方打造的专门面向民营经济的综合性政企服务平台&#xff0c;是一条直达民营企业的“信息高速路”。 记者14日从贵阳市…

【力扣】111、二叉树的最小深度

111、二叉树的最小深度 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。 说明&#xff1a;叶子节点是指没有子节点的节点。 // var minDepth function(root){if(!root) return 0;const stack [ [ root ,1] ];//…

dva-源码解析-下

首先这是一篇找妈妈的故事&#xff0c; model中的state&#xff0c;reducers&#xff0c;effects&#xff0c;是如何找到各自的妈妈呢&#xff1f;23333&#xff5e; dva 是对redux、react-redux、react-router、redux-saga的整合&#xff0c;所以在看dva源码之前建议先要熟悉这…

C++Primer : 第十二章 :allocator类

当分配一大块内存时&#xff0c;我们通过计划在这块内存上按需求构造对象。在此情况下&#xff0c;我们希望将内存分配和对象构造分离。这意味着我们可以分配大块内存&#xff0c;但是真正需要时才真正执行对象创建操作。 标准库allocator类定义在头文件memory中&#xff0c;它…

laravel 用户认证简单示例

一、模型代码&#xff1a; 实现接口&#xff1a;\Illuminate\Contracts\Auth\Authenticatable 并引入trait&#xff1a;\Illuminate\Auth\Authenticatable <?phpnamespace App\Model;use Illuminate\Database\Eloquent\Model;class Manager extends Model implements \Illu…