Smart Pointers
- std::unique_ptr - single ownership
- std::shared+ptr - shared ownership
- std::weak_ptr - temp / no ownership
Inroduced in C++ 11
头文件:memory
unique_ptr
std::unique_ptr<T> t1 = new T();// non-assignable
std::unique_ptr<T> t1(new T());//OK
std::unique_ptr<T> t1 = std::make_unique<T>();// preferred
auto t2 = std::make_unique<T>();// preferred
std::unique_ptr<T> t2 = t1;// non-copyable
std::unique_ptr<T> t2 = std::move(t1);// movable,transfer ownership
foo(std::move(t1));// transfer ownership
Example
class T {
public:
T() {
puts("T created !");
}
~T() {
puts("T destroied !");
}
};
void ex1() {
puts("Entering ex1");
{
puts("Entering ex1::scope1");
auto t1 = std::make_unique<T>();
puts("Leaving ex1::scope1");
}
puts("Leaving ex1");
}
//输出
// Entering ex1
// Entering ex1::scope1
// T created !
// Leaving ex1::scope1
// T destroied !
// Leaving ex1
void foo(std::unique_ptr<T>) {
puts("Entering foo");
puts("Leaving foo");
}
void ex2() {
puts("Entering ex2");
auto t1 = std::make_unique<T>();
foo(std::move(t1));
//e1 was destroied
puts("Leaving ex2");
}
//输出
// Entering ex2
// T created !
// Entering foo
// Leaving foo
// T destroied !
// Leaving ex2
生命周期:调用结束时,自动销毁。
shared_ptr
生命周期:use_count为0时,自动销毁。
std::shared_ptr<T> t1(new T());//OK
std::shared_ptr<T> t1 = std::make_shared<T>();// preferred
auto t1 = std::make_shared<T>();// preferred
std::shared_ptr<T> t2 = t1;// copyable,use_count + 1
std::shared_ptr<T> t2 = std::move(t1);// movable,use_count remains
foo(std::move(t1));// use_count remains
foo(t1); //use_count + 1
Example
void ex3(){
puts("Entering ex3");
auto t1 = std::make_shared<T>();
std::cout << t1.use_count() << std::endl;
{
puts("Entering ex3::scope1");
auto t2 = t1;
std::count << t1.use_count() << std::endl;
auto t3 = std::move(t2);
std::cout<< t1.use_count() << std::endl;
puts("Leaving ex3::scope1");
}
std::cout << t1.use_count() << std::endl;
puts("Leaving ex3");
}
//输出
// Entering ex3
// T created!
// 1
// Entering ex3::scope1
// 2
// 2
// Leaving ex3::scope1
// 1
// Leaving ex3
// T destoryed!
weak_ptr Temp/No Ownership
- 在访问之前必须转换为 std::shared_ptr
auto t1 = std::make_shared<T>();
std::weak_ptr<T> tw = t1; //从 shared_ptr 中构造
if(std::shared_ptr<T> t2 = tw.lock()) //转换到 shared_ptr
t2->DoSonmething();
Example
void observe(std::weak_ptr<T> tw) {
if(std::shared_ptr<T> spt = tw.lock()) {
std::cout << spt.use_count() << std::endl;
std::cout << "T still alive!" << std::endl;
}
else {
std::cout << "T was expired :(" << std::endl;
}
}
void ex4() {
puts("Entering ex4");
std::weak_ptr<T> tw;
{
puts("Entering ex4::scope1");
auto t1 = std::make_shared<T>();
std::cout << t1.use_count() <<std::endl;
tw = t1; //use_count remians
std::cout << t1.use_count() << std::endl;
observe(tw);
puts("Leaving ex4::scope1");
}
observe(tw);
puts("Leaving ex4");
}
//输出
// Entering ex4
// Entering ex4::scope1
// T created!
// 1
// 1
// 2
// T still alive!
// Leaving ex4::scope1
// T destoried!
// T was expired:(
// Leaving ex4
Conclusion
- Time to say goobye to new / delete
- Replace raw pointers with smart pointers
- prefer std::unique_ptr over std::shared_ptr
- Move std::shared_ptr whenever possible
文章笔记视频来源