c++——智能指针学习(shared_ptr和weak_ptr)
先看一个例子:Stark和Targaryen家族你中有我,我中有你。我们设计以下类企图避免内存泄漏,使得析构函数都能调用到:
#include<iostream>
#include<memory>
using namespace std; class Stark;
class Targaryen; class Stark
{
private:
Targaryen *targaryen; public:
void prin(){cout<<"stark love targaryen"<<endl;}
~Stark()
{
delete targaryen;
cout<<"~Stark"<<endl;
}
}; class Targaryen
{
private:
Stark *stark; public:
void prin() { cout << "targaryen love stark" << endl; }
~Targaryen()
{
delete stark;
cout << "~Targaryen" << endl;
}
}; int main()
{
Targaryen *tar = new Targaryen;
Stark *stark = new Stark; delete stark; system("pause");
return 0;
}
打印结果:

正常来说,我们要求的结果是两个对象都要析构掉,但是我们可以debug执行看到,并没有全部析构,显然不是我们的需求!
那么换一种智能指针的写法,看看结果怎么样:
class Stark;
class Targaryen; class Stark
{
private:
//Targaryen *targaryen;
shared_ptr<Targaryen> share_tar;
public:
void prin(){cout<<"stark love targaryen"<<endl;}
void setTargaryen(shared_ptr<Targaryen> tar)
{
this->share_tar = tar;
}
~Stark()
{
//delete targaryen;
cout<<"~Stark"<<endl;
}
}; class Targaryen
{
private:
//Stark *stark;
shared_ptr<Stark> share_stark;
//weak_ptr<Stark> weak_stark; public:
void prin() { cout << "targaryen love stark" << endl; }
void setStark(shared_ptr<Stark> stark)
{
this->share_stark = stark;
}
~Targaryen()
{
//delete stark;
cout << "~Targaryen" << endl;
}
}; int main()
{
weak_ptr<Stark> wpstark;
weak_ptr<Targaryen> wptar; //Targaryen *tar = new Targaryen;
//Stark *stark = new Stark;
{
shared_ptr<Targaryen> tar(new Targaryen);
shared_ptr<Stark> stark(new Stark);
tar->prin();
stark->prin();
tar->setStark(stark);
stark->setTargaryen(tar);
wpstark = stark;
wptar = tar;
cout << tar.use_count() << endl;
cout << stark.use_count() << endl;
} cout << wpstark.use_count() << endl;
cout << wptar.use_count() << endl; //delete stark; system("pause");
return 0;
}
我们希望在main中第一对{}号结束的时候,打印析构函数,但是并没有

那我们再换一种写法:
class Stark;
class Targaryen; class Stark
{
private:
//Targaryen *targaryen;
shared_ptr<Targaryen> share_tar;
public:
void prin(){cout<<"stark love targaryen"<<endl;}
void setTargaryen(shared_ptr<Targaryen> tar)
{
this->share_tar = tar;
}
~Stark()
{
//delete targaryen;
cout<<"~Stark"<<endl;
}
}; class Targaryen
{
private:
//Stark *stark;
//shared_ptr<Stark> share_stark; ////这里变了~~~~~~~~~~~~
weak_ptr<Stark> weak_stark; public:
void prin() { cout << "targaryen love stark" << endl; }
void setStark(shared_ptr<Stark> stark)
{
this->weak_stark = stark;
}
~Targaryen()
{
//delete stark;
cout << "~Targaryen" << endl;
}
};
这次结果还是令人满意的。

那么问题来了,为什么要这么做呢?为什么要用weak_ptr取代shared_ptr呢?
我们看weak_ptr的官方定义:
std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(“弱”)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。
std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。
std::weak_ptr 的另一用法是打断 std::shared_ptr 所管理的对象组成的环状引用。若这种环被孤立(例如无指向环中的外部共享指针),则 shared_ptr 引用计数无法抵达零,而内存被泄露。能令环中的指针之一为弱指针以避免此情况。
这种就是一种环状的情况。
另外,还有一点要注意:
int main()
{
{
int *a = new int;
std::shared_ptr<int> p1(a);
std::shared_ptr<int> p2(a);
}
system("pause");
return ;
}
这样写会报错。因为,析构的时候,指针a会被delete两次。因此,为了避免这种情况的发生,我们尽可能不适用new来初始化shared_ptr。而是用make_shared;
class Mars
{
public:
Mars ()
{
cout << this << ": Mars" << endl;
}
~Mars()
{
cout << this << ": ~Mars" << endl;
}
};
int main()
{
{
Mars pMars;
shared_ptr<Mars> p1 = make_shared<Mars >(pMars);
shared_ptr<Mars> p2 = make_shared<Mars >(pMars);
}
system("pause");
return ;
}
这玩意儿太复杂了~只是清楚大概是干什么的。但是还不会用……以及什么时候用,关键是我们这公司平时也不用,这就尴尬了。
用shared_ptr,不用new
使用weak_ptr来打破循环引用
用make_shared来生成shared_ptr
用enable_shared_from_this来使一个类能获取自身的shared_ptr
结束!以后有时间再慢慢研究。
大部分都是抄的:
https://zh.cppreference.com/w/cpp/memory/shared_ptr
https://www.cnblogs.com/wxquare/p/4759020.html
https://blog.csdn.net/worldwindjp/article/details/18843087
https://heleifz.github.io/14696398760857.html
c++——智能指针学习(shared_ptr和weak_ptr)的更多相关文章
- C++ | 再探智能指针(shared_ptr 与 weak_ptr)
上篇博客我们模拟实现了 auto_ptr 智能指针,可我们说 auto_ptr 是一种有缺陷的智能指针,并且在C++11中就已经被摈弃掉了.那么本章我们就来探索 boost库和C++11中的智能指针以 ...
- C++11 新特性之智能指针(shared_ptr, unique_ptr, weak_ptr)
这是C++11新特性介绍的第五部分,涉及到智能指针的相关内容(shared_ptr, unique_ptr, weak_ptr). shared_ptr shared_ptr 基本用法 shared_ ...
- C++智能指针: auto_ptr, shared_ptr, unique_ptr, weak_ptr
本文参考C++智能指针简单剖析 内存泄露 我们知道一个对象(变量)的生命周期结束的时候, 会自动释放掉其占用的内存(例如局部变量在包含它的第一个括号结束的时候自动释放掉内存) int main () ...
- Qt 智能指针学习(7种指针)
Qt 智能指针学习 转载自:http://blog.csdn.net/dbzhang800/article/details/6403285 从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ ...
- C++ 智能指针学习
C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849 ...
- 【C++11新特性】 C++11智能指针之shared_ptr
C++中的智能指针首先出现在“准”标准库boost中.随着使用的人越来越多,为了让开发人员更方便.更安全的使用动态内存,C++11也引入了智能指针来管理动态对象.在新标准中,主要提供了shared_p ...
- C++智能指针之shared_ptr与右值引用(详细)
1. 介绍 在 C++ 中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄露.解决这个问题最有效的方法是使用智能指针(smart pointer).智能指针是存储指向动态分配(堆)对象指针 ...
- 智能指针之shared_ptr基本概述
1.shared_ptr允许有多个指针指向同一个对象,unique_ptr独占所指向的对象. 2.类似于vector,智能指针也是模板.创建智能指针: shared_ptr<string> ...
- 【STL学习】智能指针之shared_ptr
前面已经学习过auto_ptr,这里补充另外一种智能指针,比auto_ptr要更强力更通用的shared_ptr. shared_ptr 简介及使用选择 几乎所有的程序都需要某种形式的引用计数智能指 ...
随机推荐
- shiro三连斩之第一斩
通过JavaSE,创建不同的 realm ,由简单到复杂一步步的深入的理解shiro完成认证与授权内在联系 推荐从下向上一步步的测试,每一个方法都有详细的注释,说明 从哪里来-->到哪里去,理 ...
- python模块和包(模块、包、发布模块)
模块和包 目标 模块 包 发布模块 01. 模块 1.1 模块的概念 模块是 Python 程序架构的一个核心概念 每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块 模块名 同样也 ...
- VFS 上传文件到sftp 报错 包含中文路径 或者中文文件名称
之前用Apache commons-vfs工具进行ftp操作(FTP服务器是 FileZilla Server) 上传本地文件 到 ftp服务器上,如果文件名称 包含 中文 报错 org.apache ...
- nmap扫描测试
- 关于windows映射网络驱动器,登录时重新连接
如果想登录系统后映射盘符还在,但是不自动连接,则参考下面方法.方法其实很简单,关键的步骤是:登录共享的时候,登录界面取消选中“保存凭据”,然后映射的时候,选择“下次开机是重新连接” 这样,下次开机的时 ...
- 丰富的else语句以及简介的with语句
1.if···else略 2.while.for与else Python中的循环语句(无论是while 还是for)中,经常配合continue和break语句,此时,可以和else搭配使用,当循环正 ...
- Python01(linux基础)
聊一聊计算机 CPU,电源相关,时钟部分(主频),存储器,输入输出系统 计算机记忆装置:存储器分两大类:1.内存Ram(速度快,容量小(相对),断电后内容丢失) 非持久性记忆存储器2.如:硬盘,(速度 ...
- vue-router 重难点总结笔记
1,使用动态路由配置的(如:‘:id’),可以在this.$router.params.id获得. 官网例子: 模式 匹配路径 $route.params /user/:username /user/ ...
- swift4.0 数据转模型
swift 4.0时代的到来,说明了swift已经趋于稳定了,已经完全可以入坑了. 下面就拿最简单的数据转模型来说说,实战一下. 接口使用: http://116.211.167.106/api/l ...
- json模块
dic = {"name":"boke","age":"18"} #字典 data = json.dumps(dic) ...