C++primer智能指针的笔记

介绍

为了更容易的使用动态内存,标准库提供了两种智能指针和一个伴随类。智能指针在使用完毕后会自动释放十分方便,但不规范而使用还是会造成错误。

shared_ptr

定义

智能指针也是模板需要我们提供额外的信息(指向的对象)。

shared_ptr<int> p1;//空指针,可以指向一个int

使用make_shared 函数

初始化shared_ptr最安全的方法是使用make_shared函数。

shared_ptr<int> p3=make_shared<int>(42)//p3指向一个值为42的int的shared_ptr

调用make_shared传递的参数必须与所用类型的某个构造函数相匹配,若我们没传参数,则会进行值初始化。

用另一个shared_ptr来初始化

shared_ptr<int> p4(p3);p4和p3指向相同的内存

使用new来初始化一个shared_ptr

shared_ptr<int> p5=shared_ptr<int>(new int(42));

值得注意的是shared_ptr的构造函数是explict的,我们无法隐式的要求一个shared_ptr指向new。

//这样是错误的!
shared_ptr<int> p5=new int(42);

用new初始化shared_ptr是不安全的,我们后面再来讨论。

使用

多个shared_ptr可以指向相同的内存,且当最后一个shared_ptr销毁时,指向的内存才会销魂。我们可以利用shared_ptr在多个对象间共享数据。

拷贝和赋值

当进行拷贝和赋值时,每个shared_ptr都会记录有多少个其他的shared_ptr指向相同的对象。

auto p=make_shared<int>(42);引用者只有一个
auto q(p);现在有两个
auto w=make_shared<int>(32);
q=w;32的引用者+1,42的引用者-1;42的引用者为0时会自动释放。

自动销毁

我们知道当引用者为0时就会自动销毁。

void use_factory(T arg)
{
	shared_ptr<Foo> p=factory(arg);//离开函数后p指向内存自动释放
}

shared_ptr是使用析构函数进行释放的。

shared_ptr易错点:

new和shared_ptr

当我们使用New来初始化shared_ptr时,很容易将同一块内存绑定在多个独立创建的shared_ptr上。

//下面代码只是例子,会造成double free
int *x(new int(1024));
 shared_ptr<int> k(x);
 shared_ptr<int> l(x);
 cout<<k.use_count ()<<endl;
 cout<<l.use_count()<<endl;
 //k和l同时指向x内存但它们是独立创建的,也就是说它们的引用是各自计算的,同时它们会二次释放同一块内存,造成错误。

get

不要用get初始化另一个智能指针或为另一个智能指针赋值。get返回的是一个普通的指针。

shared_ptr<int> p(new int(42)>;
int *q=p.get();//q和p指向同一块内存.
{
	shared_ptr<int> t(q);
}
//此时p,q指向内存被释放,任何解引用p,q操作都是未定义的,且在程序结束时会造成double free

unique_ptr

unique_ptr拥有它所指向的对象。当一个unique_ptr销毁时,它所指向的内存也会销毁。

初始化

unique_ptr不支持普通的拷贝和赋值操作

unique_ptr<string> p1((new) string("Stegosaurus"));
unique_ptr<string> p2(p1); //不支持拷贝!
unique_ptr<string> p3=p2; //不支持赋值!

改变unique_ptr的指向

虽然我们不能直接通过赋值来改变unique_Ptr的指向,但我们可一通过release和reset将指针的所有权转移。

u.release() //u放弃指针的所有权,返回指针,将u置空
u.reset() //释放U指向的对象
u.reset(q),如果提供了内置指针q,u就会指向这个对象

下面是例子

unique_ptr<string> p2(p1.release());//p1置空,p2指向p1
unique_ptr<string> p3(new string("Trex"));
p2.reset(p3.release());//释放p2所指内存,p2接管p3所指内存,并将p3置空

从函数返回unique_ptr

不能拷贝unique_ptr但是有个例外,我们可一返回或赋值一个将被销毁的unique_ptr。

unique_ptr<int> clone(int p)
{
	return unique_ptr<int>(new int(p));

weak_ptr

weak_ptr是一个弱引用,它不会控制所指向对象的生存期,它指向一个shared_ptr所管理的对象.一旦最后一个shared_ptr被销毁,其所指的对象也会被销毁。

shared_ptr<int> p =make_shared<int>(42);
weak_ptr<int> wp(p);//p引用不会变

使用

当我们使用一个weak_ptr时,我们并不知道它所指的对象是否还存在。我们可以调用lock来返回它所指向的对象。

if (shared_ptr<int> np=wp.lock())//若wp所指对象还存在就会返回一个指向对象的shared_ptr指针,若不存在则会返回一个空的shared_ptr
{
	//在此函数体内,可安全使用所指对象。
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值