智能指针 - 现代C++新特性总结
C++98中的智能指针通过一个模板类auto_ptr来实现,new操作符返回的指针可以交由它来管理,程序员不用再显式的调用delete,这在一定程度上避免了堆内存忘记释放的问题;不过auto_ptr有一些缺点,比如拷贝时返回一个左值,不能调用delete[]等。
C++11中废弃了auto_ptr,改用unique_ptr、shared_ptr、weak_ptr等智能指针来自动回收堆分配对象,使内存管理更安全,智能指针的使用场景也变得更全面。
unique_ptr和shared_ptr
unique_ptr是唯一性智能指针,无法进行复制,但是可以移动。而shared_ptr是共享性智能指针,采用引用计数,可以拷贝和移动,移动时引用计数不会变化。
Example
#include <memory>
#include <iostream>
using namespace std;
int main()
{
unique_ptr<int> up1(new int(11));
unique_ptr<int> up2 = up1; //不能通过编译
cout << *up1 << endl; //11
unique_ptr<int> up3 = move(up1); //现在p3是数据唯一的unique_ptr智能指针
cout << *up3 << endl; //11
cout << *up1 << endl; //运行时错误
up3.reset(); //显式释放内存
up1.reset(); //不会导致运行时错误
cout << *up3 << endl; //运行时错误
shared_ptr<int> sp1(new int(22));
shared_ptr<int> sp2 = sp1;
cout << *sp1 << endl; //22
cout << *sp2 << endl; //22
sp1.reset();
cout << *sp2 << endl; //22
}
//编译选项:g++ -std=c++11 unique_share.cpp
上例中,指针调用reset成员时,智能指针都可能释放其拥有的堆内存。
从代码中可以看出,unique_ptr和shared_ptr在对所占内存的共享上还是有一定区别的。
unique_ptr不能与其他unique_ptr类型的指针共享所指对象的内存。比如unique_ptr up2 = up1;不能通过编译,由于up1唯一地占有了new分配的堆内存,所以up2无法共享其“所有权”。这种“所有权”仅能通过标准库的move函数来转移。unique_ptr up3 = move(up1)语句中up3通过move函数夺去了up1的“所有权”,后段使用的*up1就会出现运行时错误。
而shared_ptr允许多个智能指针共享地“拥有”同一堆分配对象的内存。与unique_ptr不同的是,一旦一个shared_ptr指针放弃了“所有权”,其他的shared_ptr对对象内存的引用并不会受到影响。上例中的sp2很好说明了这个状况,sp1调用了reset成员,只是使得引用计数的降低,不会导致堆内存的释放。只有在引用计数归零时,shared_ptr才会真正地释放所占有的堆内存的空间。
weak_ptr
弱智能指针,通常指向一个共享性智能指针,当要使用所指向的共享性智能指针时,使用lock方法获取,并验证共享性智能指针的有效性。
Example:
#include <memory>
#include <iostream>
using namespace std;
void Check(weak_ptr<int> &wp)
{
shared_ptr<int> sp = wp.lock(); //转换为shared_ptr<int>
if (sp != nullptr)
cout << "still " << *sp << endl;
else
cout << "pointer is invalid." << endl;
}
int main()
{
shared_ptr<int> sp1(new int(22));
shared_ptr<int> sp2 = sp1;
weak_ptr<int> wp = sp1; //指向shared_ptr<int>所指对象
cout << *sp1 << endl; //22
cout << *sp2 << endl; //22
Check(wp); //still 22
sp1.reset();
cout << *sp2 << endl; //22
Check(wp); //still 22
sp2.reset();
Check(wp); //pointer is invalid
return 0;
}
//编译选项:g++ -std=c++11 weak.cpp
上例中定义了2个shared_ptr——sp1和sp2,而weak_ptr wp同样指向该对象内存。当sp1和sp2有效时,调用wp的lock(),check会输出still 22。当分别调用sp1和sp2的reset()时,会导致堆内存对象的引用计数降为0。一旦引用计数归0,shared_ptr就会释放对内存空间,使之失效。
整个过程中,只有shared_ptr参与了引用计数,而weak_ptr没有影响其指向的内存的引用计数。因此可以验证shared_ptr指针的有效性。
简单情况下,程序员用unique_ptr代替以前使用auto_ptr就可以使用C++11中的智能指针。而shared_ptr及weak_ptr则可用在用户需要引用计数的地方。
智能指针 - 现代C++新特性总结的更多相关文章
- [转]C++智能指针的创建
zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉.在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养 ...
- c++ 智能指针【转载】
zero 坐在餐桌前,机械的重复“夹菜 -> 咀嚼 -> 吞咽”的动作序列,脸上用无形的大字写着:我心不在焉.在他的对面坐着 Solmyr ,慢条斯理的吃着他那份午餐,维持着他一贯很有修养 ...
- C++ | 智能指针初探
智能指针初探 在 c/c++ 语言中有一种特殊的类型--指针类型. 指针作为实体,是一个用来保存一个内存地址的计算机语言中的变量.它可以直接对内存地址中的数据进行操作,是一种非常灵活的变量.指针被誉为 ...
- C++智能指针(auto_ptr)详解
智能指针(auto_ptr) 这个名字听起来很酷是不是?其实auto_ptr 只是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势,但也有其局限.本文总结的8个问题足 ...
- Android系统智能指针的设计思路(轻量级指针、强指针、弱指针)
本博客为原创,转载请注明出处,谢谢. 参考博文:Android系统的智能指针(轻量级指针.强指针和弱指针)的实现原理分析 C++中最容易出错的地方莫过于指针了,指针问题主要有两类,一是内存泄露,二是无 ...
- C++中的智能指针(auto_ptr)
实际上auto_ptr 仅仅是C++标准库提供的一个类模板,它与传统的new/delete控制内存相比有一定优势.使用它不必每次都手动调用delete去释放内存.当然有利也有弊,也不是全然完美的. 本 ...
- STL 智能指针
转自: https://blog.csdn.net/k346k346/article/details/81478223 STL一共给我们提供了四种智能指针:auto_ptr.unique_ptr.sh ...
- 【校招面试 之 C/C++】第25题 C++ 智能指针(一)之 auto_ptr
1.智能指针背后的设计思想 我们先来看一个简单的例子: void remodel(std::string & str) { std::string * ps = new std::string ...
- 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr
什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...
随机推荐
- iOS - 布局NSLayoutConstraint动画的实现
抛出问题:为何在用到用到constraint的动画时以下代码无法实现动画的功能 ,没有动画直接刷新UI跳到80 - (void)touchesBegan:(NSSet<UITouch *> ...
- 在MyEclipse(2015)中上传项目到github的步骤(很详细)
(图文)在MyEclipse(2015)中上传项目到github的步骤(很详细) git|smartGit使用详解 SmartGit使用教程
- CSS-筛选 获取第一个td
tr td:first-child{ font-weight:bold; } 看样子,应该是jquery中有些筛选,css也是能够同样进行筛选的,只是模式有些可能不同 a[data-toggle*=' ...
- PS合成以及分解GIF
http://jingyan.baidu.com/article/3052f5a1c91f0497f31f862a.html 百度上的这个说明很详细了 这里就简单注明一下: PS 时间轴:用来创建动画 ...
- Java 8 特性 – 终极手册
简介 毫无疑问,Java 8的发布是自Java 5(它的发布已远在2004年)以来在Java世界中最重大的事情.它带来了超多的新特性,这些特性分别被加入到Java语言本身.Java编译器.类库.工具类 ...
- 题目1458:汉诺塔III(不一样的汉诺塔递归算法)
题目链接:http://ac.jobdu.com/problem.php?pid=1458 详解链接:https://github.com/zpfbuaa/JobduInCPlusPlus 参考代码: ...
- Windows正向绑定shell和反向反弹shell的Python代码
Windows下的shell原理 经过查阅资料,使用os.dup2(nfd, ofd)的方式重定向socket的输入输出到windows系统的cmd是无法做到的,属于系统原因,不能直接复制Linux下 ...
- 自定义vue全局组件use使用
自定义一个全局Loading组件,并使用:总结目录:|-components |-loading |-index.js 导出组件,并且install |-loading.vue 定义Loading组件 ...
- K-means中的K值选择
关于如何选择Kmeans等聚类算法中的聚类中心个数,主要有以下方法(译自维基): 1. 最简单的方法:K≍sqrt(N/2) 2. 拐点法:把聚类结果的F-test值(类间Variance和全局Var ...
- 使用python语言操作MongoDB
MongoDB是一个跨平台的NoSQL,基于Key-Value形式保存数据.其储存格式非常类似于Python的字典,因此用Python操作MongoDB会非常的容易. pymongo的两种安装命令 p ...