聊聊智能指针 auto_ptr、shared_ptr、weak_ptr和unique_ptr
本文为转载:https://www.cnblogs.com/zeppelin5/p/10083597.html,对作者有些地方做了修正。
手写代码是理解C++的最好办法,以几个例子说明C++四个智能指针的用法,转载请注明出处。
一、auto_ptr
auto_ptr这是C++98标准下的智能指针,现在常常已经被C++标准的其他智能指针取代。它的缺点是在转移所有权后会使运行期不安全。C++11新标准,用unique_ptr来代替auto_ptr原有功能,其用法介绍见第四部分unique_ptr。
#include <iostream>
#include <memory>
#include <string>
using namespace std; void main(){
auto_ptr<string> country[] =
{
auto_ptr<string>(new string("USA")),
auto_ptr<string>(new string("CHN")),
auto_ptr<string>(new string("RUS")),
auto_ptr<string>(new string("FRA")),
auto_ptr<string>(new string("GRB"))
}; auto_ptr<string> pwin;
pwin = country[]; //将所有权从country[2]转让给pwin,此时country[2]不再引用该字符串从而变成空指针,在运行到循环时就会崩溃 for (int i = ; i < ; ++i)
cout << *country[i] << endl;//运行到[2]时崩溃,因为country[2]为空
cout << "The best is " << *pwin << endl; system("pause");
}
二、share_ptr
share_ptr是C++11新添加的智能指针,它限定的资源可以被多个指针共享。
用法见下例:
#include <iostream>
#include <memory>
#include <string>
using namespace std; void fun(){
shared_ptr<string> pa(new string("CHN"));
shared_ptr<string> pb(new string("USA"));
cout << "*pa " << *pa << endl;//CHN
cout << "pa.use_count " << pa.use_count() << endl;//
cout << "*pb " << *pb << endl;//USA
cout << "pb.use_count " << pb.use_count() << endl;// pa = pb;
cout << *pa << endl;//USA
cout << "pa.use_count " << pa.use_count() << endl;//2:pa和pb指向同一个资源USA了,该资源的计数为2,所以pb、pb都输出2
cout << "pb.use_count " << pb.use_count() << endl;// pa.reset();
pb.reset();
cout << "pa.use_count " << pa.use_count() << endl;//
cout << "pb.use_count " << pb.use_count() << endl;//
} void main()
{
fun();
system("pause");
}
与数组相结合应用,见另一个例子:
#include <iostream>
#include <memory>
#include <string>
using namespace std; void main(){
shared_ptr<string> country[] =
{
shared_ptr<string>(new string("USA")),
shared_ptr<string>(new string("CHN")),
shared_ptr<string>(new string("RUS")),
shared_ptr<string>(new string("FRA")),
shared_ptr<string>(new string("GRB"))
}; shared_ptr<string> pwin;
cout << pwin.use_count() << endl;//输出0
pwin = country[];
/*使用shared_ptr时运行正常,因为shared_ptr采用引用计数,pwin和films[2]都指向同一块内存,
在释放空间时因为事先要判断引用计数值的大小因此不会出现多次删除一个对象的错误。 从名字share就可以看出了资源可以被多个指针共享,它使用计数机制来表明资源被几个指针共享。
可以通过成员函数use_count()来查看资源的所有者个数。
*/
cout << pwin.use_count() << endl;//输出2 for (int i = ; i < ; ++i)
cout << *country[i] << endl;//对比auto_ptr,这里就不会崩溃,正常的输出所有的string字符串。
cout << "The best is " << *pwin << endl; system("pause");
}
三、weak_ptr
weak_ptr是一种用于解决shared_ptr相互引用时产生死锁问题的智能指针。如果有两个shared_ptr相互引用,那么这两个shared_ptr指针的引用计数永远不会下降为0,资源永远不会释放。weak_ptr是对对象的一种弱引用,它不会增加对象的use_count,weak_ptr和shared_ptr可以相互转化,shared_ptr可以直接赋值给weak_ptr,weak_ptr也可以通过调用lock函数来获得shared_ptr。
先看一下两个shared_ptr指针互相引用导致的资源释放失败的例子:
#include <iostream>
#include <memory>
#include <string>
using namespace std; class B;
class A
{
public:
shared_ptr<B> pb_;
~A()
{
cout << "A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
}; void fun(){
shared_ptr<B> pb(new B());
cout << "pb.use_count " << pb.use_count() << endl;//
shared_ptr<A> pa(new A());
cout << "pa.use_count " << pa.use_count() << endl;// pb->pa_ = pa;
cout << "pb.use_count " << pb.use_count() << endl;//
cout << "pa.use_count " << pa.use_count() << endl;//
pa->pb_ = pb;
cout << "pb.use_count " << pb.use_count() << endl;//2:由于share_ptr是共享资源,所以pb所指向的资源的引用计数也会加1
cout << "pa.use_count " << pa.use_count() << endl;//
}//程序结束时,没有调用A和B的析构函数 void main()
{
fun();
system("pause");
}
而使用weak_ptr:把A中的shared_ptr<B> pb_改为weak_ptr<B> pb_weak,这样改为了弱引用,传递时不会增加pb引用计数use_count()的值,所以最终能够使A、B资源正常释放:
#include <iostream>
#include <memory>
#include <string>
using namespace std; class B;
class A
{
public:
weak_ptr<B> pb_weak;
~A()
{
cout << "A delete\n";
}
};
class B
{
public:
shared_ptr<A> pa_;
~B()
{
cout << "B delete\n";
}
void print(){
cout << "This is B" << endl;
}
}; void fun(){
shared_ptr<B> pb(new B());
cout << "pb.use_count " << pb.use_count() << endl;//
shared_ptr<A> pa(new A());
cout << "pa.use_count " << pa.use_count() << endl;// pb->pa_ = pa;
cout << "pb.use_count " << pb.use_count() << endl;//
cout << "pa.use_count " << pa.use_count() << endl;// pa->pb_weak = pb;
cout << "pb.use_count " << pb.use_count() << endl;//1:弱引用不会增加所指资源的引用计数use_count()的值
cout << "pa.use_count " << pa.use_count() << endl;// shared_ptr<B> p = pa->pb_weak.lock();
p->print();//不能通过weak_ptr直接访问对象的方法,须先转化为shared_ptr
cout << "pb.use_count " << pb.use_count() << endl;//
cout << "pa.use_count " << pa.use_count() << endl;//
}//函数结束时,正确的情况下,应该调用A和B的析构函数 /*资源B的引用计数一直就只有1,当pb析构时,B的计数减一,变为0,B得到释放,
B释放的同时也会使A的计数减一,同时pa自己析构时也会使资源A的计数减一,那么A的计数为0,A得到释放。
*/ void main()
{
fun();
system("pause");
}
四、unique_ptr
unique_ptr 是一个独享所有权的智能指针,它提供了严格意义上的所有权。它取代了C++98中的auto_ptr。
用法和auto_ptr类似,详情见一下代码:
#include <iostream>
#include <memory>
#include <string>
using namespace std; unique_ptr<string> fun2(){
return unique_ptr<string>(new string("RUS"));
} void fun(){
unique_ptr<string> pa(new string("CHN"));
//unique_ptr没有use_count()方法
unique_ptr<string> pb(new string("USA")); pb = move(pa);
//p2=p1;//错误,不能直接用等于号
if (pa == nullptr)
cout << "pa现在为空" << endl; cout << "*pb " << *pb << endl;//pb变成了“CHA” string* ps = pb.release();//清空当前智能指针所指的资源对象,并返回指针
cout << "*ps " << *ps << endl;//ps变成了“CHA” pa.reset(ps);//重置指向另一个对象
cout << "*pa " << *pa << endl;//pa变成了“CHA” pb = fun2();//接收函数的返回值可以用等于号,因为使用了移动构造函数
cout << "*pb " << *pb << endl;//pb变成了“RUS”
} void main()
{
fun();
system("pause");
}
聊聊智能指针 auto_ptr、shared_ptr、weak_ptr和unique_ptr的更多相关文章
- 智能指针auto_ptr & shared_ptr
转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...
- C++智能指针: auto_ptr, shared_ptr, unique_ptr, weak_ptr
本文参考C++智能指针简单剖析 内存泄露 我们知道一个对象(变量)的生命周期结束的时候, 会自动释放掉其占用的内存(例如局部变量在包含它的第一个括号结束的时候自动释放掉内存) int main () ...
- C++ 智能指针(shared_ptr/weak_ptr)原理分析
其主要的类关系如下所示(省略相关的类模板参数): 图1 从上面的类图可以清楚的看出shared_ptr内部含有一个指向被管理对象(managed object)T的指针以及一个__shared_cou ...
- C++ | 再探智能指针(shared_ptr 与 weak_ptr)
上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...
- 【C++11新特性】 C++11智能指针之shared_ptr
C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...
- C++智能指针之shared_ptr与右值引用(详细)
1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...
- 关于智能指针auto_ptr
智能指针auto_ptr和shared_ptr也是面试中经常被问到的一个 感觉看auto_ptr的源码反而更加容易理解一些,因为源码的代码量并不大,而且比较容易理解. 本篇主要介绍auto_ptr 其 ...
- 【C++智能指针 auto_ptr】
<More Effective C++>ITEM M9他提到auto_ptr.说是当异常产生的时候.怎么释放为对象分配的堆内存,避免反复编写内存释放语句. PS:这里书里面提到函数退出问题 ...
- 智能指针之shared_ptr基本概述
1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...
随机推荐
- ARTS Week 12
Jan 13, 2020 ~ Jan 19, 2020 Algorithm Problem 112. Path Sum (路径总和) 题目链接 题目描述:给定一棵二叉树和一个值 sum ,检查二叉树是 ...
- 手写-- K-means++
1. K-means++原理 K均值聚类属于启发式方法,不能保证收敛到全局最优,初始中心的选择会直接影响聚类结果.K-means是随机选择样本点作为聚类中心,容易造成算法局部收敛或者需要较多迭代次数, ...
- 并发编程的基石——AQS类
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文参考了[Java多线程进阶(六)-- J.U.C之l ...
- kali重置root密码
像这样,kali系统的root密码忘记了,只需一分钟时间,快速重置root密码 第一步: 电脑开机后kali系统会进入引导界面,这是我们只需 “e” 进入启动前编辑命令(若系统没有出现这个页面,大家在 ...
- 08-JavaScript基础
今日知识 1. JavaScript基础 2. 案例 3.总结 JavaScript介绍: * 概念:一门客户端脚本语言 * 运行在客户端浏览器中的,每一个浏览器都有JavaScript的解析引擎 * ...
- 详解CopyOnWrite容器及其源码
详解CopyOnWrite容器及其源码 在jave.util.concurrent包下有这样两个类:CopyOnWriteArrayList和CopyOnWriteArraySet.其中利用到了Cop ...
- Linux 查看CPU、内存、机器型号等硬件信息
# 查看CPU信息 #查看CPU信息(型号) [root@localhost ~]# cat /proc/cpuinfo | grep name | cut -f2 -d: | uniq -c 32 ...
- windows服务器 IIS FTP服务
一.安装ftp,如果服务器没有,去windows组件里面装一下. 安装IIS,安装FTP(版本不同,选项不相同,这两项必选) 二.装完之后在IIS管理中心创建FTP站点 创建类型 ftp站点: ...
- 使用ASP.NET Core构建RESTful API的技术指南
译者荐语:利用周末的时间,本人拜读了长沙.NET技术社区翻译的技术标准<微软RESTFul API指南>,打算按照步骤写一个完整的教程,后来无意中看到了这篇文章,与我要写的主题有不少相似之 ...
- 文本段落缩进text-indent:2em
中文文字中的段前习惯空两个文字的空白,这个特殊的样式可以用下面代码来实现: p{text-indent:2em;} <p>1922年的春天,一个想要成名名叫尼克卡拉威(托比?马奎尔Tobe ...