智能指针shared_ptr
// 智能指针会自动释放所指向的对象。
// shared_ptr的应用场景是:程序需要在多个对象间共享数据 /* 先从应用场景入手吧,说矿工A发现了一个金矿。
* 然后矿工A喊来了矿工B,一起开采,不久后矿工A劳累过度死了。
* 矿工B继续开采着矿工A发现的金矿。
* 但是矿工B不久后得了尘肺病。
* 这时候如果矿工B喊来了矿工C,那矿工C就继续开采这个金矿,
* 如果矿工B至死都没有喊anyone,那么这个金矿不再被任何人发现。
*
* 我们来说说实现
* 每个矿工new一个对象,金矿new一个对象。
* 矿工死了就delte掉,金矿不再被发现也delte掉。
*
* 但是我们有没有可能让最后一个矿工死时,金矿被自动delte掉?
* 这样的话我们就不需要额外管理金矿对象了。
* 有可能啊,你用共享指针啊。
* 共享指针管理一个对象,管理一个引用计数。
* 每次对共享指针赋值和拷贝时,引用计数就加1。
* 当共享指针被销毁时,引用计数就减1。
* 这样就变成多个矿工间共享金矿数据了。
*
* 下面我们来说说引用计数递增的情况
* 1 用一个shared_ptr初始化另一个shared_ptr,肯定调用拷贝构造函数喽
* 2 用一个shared_ptr赋值另一个shared_ptr,肯定调用赋值函数喽
* 3 将shared_ptr作为参数传递给一个函数,这个也会调用拷贝构造函数
* 4 将shared_ptr作为函数的返回值,这个也会调用拷贝构造函数
*
* 下面我们来说说引用计数递减的情况
* 1 shared_ptr被销毁,参数出栈是被销毁的一种情况
* 2 给shared_ptr重新赋值
*
* 一旦一个shared_ptr的引用计数变为0,它就会自动释放所管理的对象。
*/ #include <iostream>
#include <memory> using namespace std; struct Gold
{
~Gold() {total = -1;}
int total{20}; Gold &operator--()
{
--total;
return *this;
} const Gold operator--(int)
{
Gold tmp = *this;
--(*this);
return Gold(tmp);
}
}; class Miner
{
public:
Miner() : gold(make_shared<Gold>()) {} Miner(const Miner &miner)
{
gold = miner.gold;
} void dig()
{
(*gold)--;
} Gold *base()
{
return gold.get();
} private:
shared_ptr<Gold> gold;
}; int main(int argc, char *argv[])
{
auto miner1 = new Miner;
auto miner2 = new Miner(*miner1); // 代码执行到这里
// @表示地址 usecount是引用计数
// miner1的gold @0x605f40
// miner2的gold @0x605f40
// shared_ptr的usecount是2
// 可见miner1和miner2的gold指向同一个对象
// 引用计数正确 auto gold = miner2->base(); // 代码执行到这里
// gold @0x605f40 miner1->dig();
cout << gold->total << endl;
miner2->dig();
cout << gold->total << endl;
miner1->dig();
cout << gold->total << endl; delete miner1; // 代码执行到这里
// miner1的gold (null)
// miner2的gold @0x605f40
// shared_ptr的usecount是1
// 引用计数正确 miner2->dig();
cout << gold->total << endl; delete miner2; // 代码执行到这里
// miner1的gold (null)
// miner2的gold @0x605f20
// miner2管理的对象(@0x605f40) 已被销毁
// 调用了Gold的析构函数
// gold->totle值为-1
// 至于miner2的gold @0x605f20 ??
// 管它呢,反正已引用不到 cout << gold->total << endl; int *p2;
{
auto p1 = make_shared<int>(5);
p2 = p1.get(); // 代码执行到这里
// p1 @0x605f60
// usecount是1
// p2 指向@0x605f60
} // 代码执行到这里
// 代码块出栈了,p1被销毁
// usecount变为0,所以p1管理的对象也被销毁了
// ***这是为什么不建议用get的原因
// 虽然可以正确输出p2所指向的对象,但是这是不确定的
// p2就是所谓的野指针了
cout << *p2 << endl; shared_ptr<int> p4;
{
auto p3 = make_shared<int>(5);
p4 = p3; // 代码执行到这里
// p3 @0x605f60
// p4 @0x605f60
// usecount是2
} // 代码执行到这里
// 代码块出栈了,p3被销毁
// usecount变为1,p3并未销毁所管理的对象
// p4所管理的对象可以正确输出
cout << *p4 << endl; return 0;
}
智能指针shared_ptr的更多相关文章
- c/c++ 智能指针 shared_ptr 和 new结合使用
智能指针 shared_ptr 和 new结合使用 用make_shared函数初始化shared_ptr是最推荐的,但有的时候还是需要用new关键字来初始化shared_ptr. 一,先来个表格,唠 ...
- c/c++ 智能指针 shared_ptr 使用
智能指针 shared_ptr 使用 上一篇智能指针是啥玩意,介绍了什么是智能指针. 这一篇简单说说如何使用智能指针. 一,智能指针分3类:今天只唠唠shared_ptr shared_ptr uni ...
- C++智能指针shared_ptr
shared_ptr 这里有一个你在标准库中找不到的—引用数智能指针.大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章.最重要的一个细节是引用数是如何被执行的—插入,意思是说你将引 ...
- STL源码剖析-智能指针shared_ptr源码
目录一. 引言二. 代码实现 2.1 模拟实现shared_ptr2.2 测试用例三. 潜在问题分析 你可能还需要了解模拟实现C++标准库中的auto_ptr一. 引言与auto_ptr大同小异,sh ...
- 智能指针shared_ptr的用法
为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...
- 智能指针 shared_ptr 解析
近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM @HQU s ...
- 智能指针shared_ptr新特性shared_from_this及weak_ptr
enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...
- C++ 智能指针 shared_ptr
今天晚上去旁听了C++高级编程的课,其中提到智能指针.第一反映还以为是auto_ptr呢,一听才知道是share_ptr这个.哦,原来是C++11特性.大致的原因是auto_ptr有一点缺陷,而sha ...
- 标准库中的智能指针shared_ptr
智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...
随机推荐
- C# DateTime变量不能赋null值
使用定时器的时候: DateTime aimtime=DateTime.Now.AddSeconds(1); CheckTimer() { if(DateTime.Now.CompareTo(aimt ...
- WKWebKit基础
UIWebView & UIWebViewDelegate 这个两个东西在 WKWebKit 中被重构成 14 个类 3 个协议. WKWebKit Framework Classes WKB ...
- html中的图片、css、js等路径加载问题
网页文件的存取路径有3种:物理路径.绝对路径和相对路径. 物理路径就是你的文件放在主机上的具体位置,例如:D:\\image\\1.jpg 这种格式,该方法可以很快确定出你的文件,但是在网页显示路径基 ...
- 为什么jQuery要返回jQuery.fn.init对象
作者:zccst jQuery = function( selector, context ) { // The jQuery object is actually just the init con ...
- Yii -- framework 目录结构说明
base 底层的类库文件 caching 所有缓存方法 cli 项目生成脚本 collecions 用PHP语言构造传统OO语言的数据存储单元.如队列,栈,哈希等等 console yii控制台 db ...
- IdTCP的C++Builder2010示例(转)
源:IdTCP的C++Builder2010示例 IdTCP的C++Builder2010示例 这个是服务端的: void __fastcall TTCPDataServer::TCPServerEx ...
- Undefined symbols for architecture armv7错误解决方法
Undefined symbols for architecture armv7: "_OBJC_CLASS_$_BriefMainModel", referenced from: ...
- &简单使用记录
最近阅读juce代码发现有很多&的用法,例如:(array.size() & 1 == 0) 的判断,仔细分析了下和1做与 操作是为了判断低位是否为0或者1,直观的说就是判断左值的奇偶 ...
- leetcode day5
[242]Valid Anagram: Given two strings s and t, write a function to determine if t is an anagram of s ...
- JDK8新特性面试
java8:http://ifeve.com/java-8-features-tutorial/ 一.Lambda表达式和函数式接口 Lambda表达式(也叫做闭包) 它允许我们将一个函数当作方法的参 ...