unique_ptr
unique_ptr简介
一个unique_ptr “拥有”它所指向的对象。与shared_ptr不同,某个时刻只能有一个unique_ptr指向一个给定的对象。即两个 unique_ptr 不能指向一个对象,unique_ptr 之所以叫这个名字,是因为它只能指向一个对象,即当它指向其他对象时,之前所指向的对象会被摧毁。其次,当 unique_ptr 超出作用域时,指向的对象也会被自动摧毁。与shared_ptr不同,没有类似make_shared的标准库函数返回一个unique_ptr。当我们定义一个unique_ptr时,需要将其绑定到一个new返回的指针上,与shared_ptr类似,初始化必须采用直接初始化的形式。与shared_ptr不同的是不能进行拷贝操作赋值操作。
unique_ptr的操作
unique_ptr< T >sp | 空智能指针 |
---|---|
p | 将p用做一个条件判断,若p指向一个对象,为true |
*p | 解引用p,获得他指向的对象 |
p->mem | 等价于(*p).mem |
p.get() | 返回p中保存的指针,使用时要小心,若智能指针释放了其对象,返回的指针所指向的对象 |
swap(p,q) | 交换p和q的指针 |
p.swap(q) | 交换p和q的指针 |
p.release() | p放弃对指针的控制权,返回指针,并并且将p置空。 |
p.reset() | 释放p指向的对象。 |
p.reset(e) | 如果提供了内置指针e,p指向这个对象;否则p置空 |
unique_ptr<int> p1;//正确,可以指向一个int的unique_ptr
unique_ptr<int> p2(new int (2));//正确,p2指向一个值为2的int
unique_ptr<int> p3(p2);//错误 不支持拷贝
unique_ptr<int> p4;
p4=p2;//错误 不支持赋值操作
unique_ptr<int>p5(p2.release());//release将p1置空,
unique_ptr<int>p6(new int(2));
p5.reset(p6.release())//reset释放了p5原先指向的内存,p6对指针的控制权给p5
p2.release()//错误,p2不会释放内存,丢失了内置的指针
auto p = p2.release()//正确,但是需要delete(p)
unique_ptr初始化
建议使用以下代码进行初始化
unique_ptr<Test> p1(new Test(100));
看一个例子:
#include<iostream>
#include<memory>
using namespace std;
int main(){
int *a = new int(100);
{
unique_ptr<int> p1(a);
}
unique_ptr<int> p2(a);
cout <<"a的值是" <<*p2<<endl; //输出的值1926192
}
上面的代码会出现未定义的操作,出现的原因p1,p2相互独立的独享a,在p1作用域完成后,会是释放a内存,所以出现未定义的操作。
传递unique_ptr参数和返回unique_ptr
不能拷贝unique_ptr的规则有一个例外:我们可以拷贝或者赋值一个将要销毁的unique_ptr。最常见的例子就是从函数返回一个unique_ptr:
#include<iostream>
#include<memory>
using namespace std;
unique_ptr<int> clone(int p){
return unique_ptr<int>(new int(p));
}
int main(){
unique_ptr<int> p2=clone(20);
cout <<"a的值是" <<*p2<<endl;//输出20
}
还可以返回一个局部对象的拷贝;
#include<iostream>
#include<memory>
using namespace std;
unique_ptr<int> clone(int p){
unique_ptr<int> ret(new int(p));
return ret;
}
int main(){
unique_ptr<int> p2=clone(20);
cout <<"a的值是" <<*p2<<endl; //输出20
}
上边两段代码,编译器都知道要返回的对象将要被销毁。在此情况下,编译器执行一种特殊的“拷贝”。
weak_ptr
weak_ptr简介
weak_ptr是一种不控制所指向对象生存期的智能指针,他指向由一个shared_ptr管理的对象,将一个weak_ptr对象绑定到一个shared_ptr不会改变shared_ptr的引用计数。一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放,即使有weak_ptr指向对象,对象还是被释放的。
weak_ptr操作
weak_ptr< T >w | 空智能指针 |
---|---|
weak_ptr<T> w(sp) | 与shared_ptr sp指向相同对象的weak_ptr. |
w=p | p可以是shared_ptr或者weak_ptr,赋值后w与p共享对象 |
w.reset() | w置空 |
w.use_count() | 与w共享对象shared_ptr的数量 |
w.expired() | 若w.use_count()==0,返回true,否则返回false |
w.lock() | 如果expired为true,返回一个空shared_ptr,否则返回一个指向w对象的shared_ptr。 |
当我们创建一个weak_ptr时我们需要用shared_ptr初始化
auto p = make_shared<int>(42)
weak_ptr<int>wp(p)//p的引用计数不会改变
由于weak_ptr的对象有可能不存在,所以访问的时候我们必须用lock。
if(shared_ptr<int>sp = wp.lock()){
//sp和p共享对象
}
#include<iostream>
#include<memory>
using namespace std;
int main(){
auto p = make_shared<int>(42);
weak_ptr<int>wp(p);//p的引用计数不会改变
if(shared_ptr<int>sp = wp.lock()){
//sp和p共享对象
*sp = 72;
}
cout << *p << endl; //输出72
}