C++智能指针简介
一、简介
前言
-
从C到C++
- C: malloc 和 free
- C++: new 和 delete
-
从C++到Morden C++
- C++: new 和 delete
- morden C++: shared_ptr, unique_ptr 和 weak_ptr
作用
更安全的使用动态内存
使用方法
(1) 使用
(2) 创建
(3) 所有权管理
- 通过 reset 方法重新指定
- 通过移动语义转移所有权
- 智能指针还可能没有对象,这种情况被称为empty
(4) 实例
int main()
{
std::shared_ptr<string> pt1(new string("C++"));
std::shared_ptr<string> pt2 = pt1;
std::weak_ptr<string> pw = pt1;
*pt1 = "Java";
pt1.reset(); //取消pt1的引用
pt2.reset(); //取消pt2的引用
return 0;
}
二、智能指针详解
(1) shared_ptr
shared_ptr是
共享所有权的智能指针
实现原理
引用计数,它的具体做法如下:
(a)当创建智能指针类的新对象时,初始化指针,并将引用计数设置为1;
(b)当能智能指针类对象作为另一个对象的副本时,拷贝构造函数复制副本的指向辅助类对象的指针,并增加辅助类对象对基础类对象的引用计数(加1);
(c)使用赋值操作符对一个智能指针类对象进行赋值时,处理复杂一点:先使左操作数的引用计数减 1,如果减1后引用计数为 0,则释放指针所指对象内存。然后增加右操作数所指对象的引用计数;
(d)完成析构函数:调用析构函数时,析构函数先使引用计数减 1,如果减至 0 则 delete 对象。
代价:
- shared_ptr 对象除了包括一个所拥有对象的指针外,还必须包括一个引用计数代理对象的指针;
- 时间上的开销主要在初始化和拷贝操作上。
注意要点:
- 可复制可移动
- reset(): 重置之前检查指针管理权,重置指针。
- get(): 只暴露指针,不释放管理权。
- swap():交换所有权,引用计数不变。
(2) unique_ptr
unique_ptr
独占所有权的智能指针
注意要点:
- 不可可复制可移动
- reset(): 删除旧指针的内存,重置指针。
- get(): 只暴露指针,不释放管理权。
- swap():交换指针。
- release(): 释放管理权
(3) weak_ptr
weak_ptr
不具有所有权的智能指针
注意要点:
- 与裸指针一样,但是获取不到裸指针
- 使用时必须转化为shared_ptr,其函数为lock()
- shared_ptr 的辅助者,破除循环引用的内存泄露。
(4)拓展部分
1.尽量使用make_shared初始化
2.智能指针作为函数的参数和返回值
3.智能指针的转化
三、结语
(1)要点:
- 智能指针不是指针,是对象
- 智能指针意味着管理权
- 理解智能指针的管理权限
(2)陷阱:
- 不要把一个原生指针给多个智能指针管理
- 记得使用release()的返回值
- 禁止delete 智能指针get 函数返回的指针
(3)各种各样的智能指针:
- Boost
- Loki基于Policy的智能指针
- Qt基于的父子对象和自身deleteLater的半自动智能指针