Smart Pointers 智能指针 - C++ Weekly EP3哔哩哔哩bilibili
为什么要使用Smart Pointer
就是new之后要不要free的麻烦,内存泄漏等问题.
引入了智能指针后,看右图:auto e = std::make_unique<Entity>()
,这个相当于是new了一个Entity的指针.
用std::move(e)
去将这个独占的指针传给形参e,那么bar函数里面就own了e。在bar执行完后e会自动销毁,就不需要主动去free.
unique_ptr
-
第一句是错的,不能用一个对象的指针去赋值给智能指针.
-
第二句是对的,但是不推荐使用.
-
第三句是对的,推荐使用
unique_ptr <Entity> e1 = make_unique<Entity>();
-
第四句是对的,推荐使用,比第三句更简便,就是把前面的变成auto
auto e2 = make_unique<Entity>();
-
第五句是错的,unique_ptr是single ownnership,所以不能对他进行一个赋值(拷贝)
-
第六句是对的,可以move,move就相当于是转移ownership.
unique_ptr<Entity> e2 = move(e1);
所以:
foo(move(e1)); // 就可以成功去传参啦!
来看一个例子:
#include <memory>
#include <string>
#include <iostream>
#include <cstdio>
using namespace std;
class Entity{
public:
Entity() {puts("Entity created!");}
~Entity(){puts("Entity destroyed!");}
};
void ex1(){
puts("--------");
puts("Entering ex1");
{
puts("Entering ex1::scope1");
auto e1 = make_unique<Entity>(); // 这里创建了Entity对象
puts("Leaving ex1::scope1");
}
// 这里作用域结束,就析构了这个对象,释放了指针
puts("Leaving ex1");
}
void foo(unique_ptr<Entity>){
puts("Entering foo");
puts("Leaving foo");
}
void ex2(){
puts("--------");
puts("Entering ex2");
auto e1 = make_unique<Entity>(); // 这里创建了Entity对象
foo(move(e1));
// 执行完foo函数后,就释放了
puts("Leaving ex2");
}
int main()
{
ex1();
ex2();
}
可以看出来,unique_ptr的生命周期就是在他的那个作用域结束后,unique_ptr就释放了.
可以看到,unique_ptr是独占的,同时刻只能有一个unique_ptr去占有这个对象,然后如果需要赋值这个unique_ptr的话,就需要用move去transfer. 然后生命周期很简单,就是在他的作用域结束后终止。 比如move到了func4,然后func4结束了,就释放了.
shared_ptr
shared_ptr的特点是,可以多个share_ptr同时共享同一个对象。 与unique_ptr一样,都是在局部作用域结束后,自动释放,不过不同的是,由于他可以多个共享,所以需要维护一个引用计数,在计数为0时才真正去删除.
- 这个非常适合多线程程序.
用法和unique_ptr非常像,唯一的区别在于他可以复制:
share_ptr<Entity> e2 = e1;
这样可以完成一个拷贝,使得shared_ptr的count+1.
来看一个例子:
- line38:创建了一个make_shared
- line42:拷贝了一个shared_ptr,所以use_count +=1 ,变成了2
- line44:将e2
传递
给了e3,use_count不变,这样e2就没用了(丧失了ownership) . - line48:离开这个作用域后,e3释放了,所以use_count -= 1, 变成了0
- 最后,e1也退出作用域了,所以自动销毁了.