// 智能指针会自动释放所指向的对象。
// 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的更多相关文章

  1. c/c++ 智能指针 shared_ptr 和 new结合使用

    智能指针 shared_ptr 和 new结合使用 用make_shared函数初始化shared_ptr是最推荐的,但有的时候还是需要用new关键字来初始化shared_ptr. 一,先来个表格,唠 ...

  2. c/c++ 智能指针 shared_ptr 使用

    智能指针 shared_ptr 使用 上一篇智能指针是啥玩意,介绍了什么是智能指针. 这一篇简单说说如何使用智能指针. 一,智能指针分3类:今天只唠唠shared_ptr shared_ptr uni ...

  3. C++智能指针shared_ptr

    shared_ptr 这里有一个你在标准库中找不到的—引用数智能指针.大部分人都应当有过使用智能指针的经历,并且已经有很多关于引用数的文章.最重要的一个细节是引用数是如何被执行的—插入,意思是说你将引 ...

  4. STL源码剖析-智能指针shared_ptr源码

    目录一. 引言二. 代码实现 2.1 模拟实现shared_ptr2.2 测试用例三. 潜在问题分析 你可能还需要了解模拟实现C++标准库中的auto_ptr一. 引言与auto_ptr大同小异,sh ...

  5. 智能指针shared_ptr的用法

    为了解决C++内存泄漏的问题,C++11引入了智能指针(Smart Pointer). 智能指针的原理是,接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈 ...

  6. 智能指针 shared_ptr 解析

    近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM   @HQU s ...

  7. 智能指针shared_ptr新特性shared_from_this及weak_ptr

    enable_shared_from_this是一个模板类,定义于头文件<memory>,其原型为: template< class T > class enable_shar ...

  8. C++ 智能指针 shared_ptr

    今天晚上去旁听了C++高级编程的课,其中提到智能指针.第一反映还以为是auto_ptr呢,一听才知道是share_ptr这个.哦,原来是C++11特性.大致的原因是auto_ptr有一点缺陷,而sha ...

  9. 标准库中的智能指针shared_ptr

    智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...

随机推荐

  1. C# DateTime变量不能赋null值

    使用定时器的时候: DateTime aimtime=DateTime.Now.AddSeconds(1); CheckTimer() { if(DateTime.Now.CompareTo(aimt ...

  2. WKWebKit基础

    UIWebView & UIWebViewDelegate 这个两个东西在 WKWebKit 中被重构成 14 个类 3 个协议. WKWebKit Framework Classes WKB ...

  3. html中的图片、css、js等路径加载问题

    网页文件的存取路径有3种:物理路径.绝对路径和相对路径. 物理路径就是你的文件放在主机上的具体位置,例如:D:\\image\\1.jpg 这种格式,该方法可以很快确定出你的文件,但是在网页显示路径基 ...

  4. 为什么jQuery要返回jQuery.fn.init对象

    作者:zccst jQuery = function( selector, context ) { // The jQuery object is actually just the init con ...

  5. Yii -- framework 目录结构说明

    base 底层的类库文件 caching 所有缓存方法 cli 项目生成脚本 collecions 用PHP语言构造传统OO语言的数据存储单元.如队列,栈,哈希等等 console yii控制台 db ...

  6. IdTCP的C++Builder2010示例(转)

    源:IdTCP的C++Builder2010示例 IdTCP的C++Builder2010示例 这个是服务端的: void __fastcall TTCPDataServer::TCPServerEx ...

  7. Undefined symbols for architecture armv7错误解决方法

    Undefined symbols for architecture armv7: "_OBJC_CLASS_$_BriefMainModel", referenced from: ...

  8. &简单使用记录

    最近阅读juce代码发现有很多&的用法,例如:(array.size() & 1 == 0) 的判断,仔细分析了下和1做与 操作是为了判断低位是否为0或者1,直观的说就是判断左值的奇偶 ...

  9. leetcode day5

    [242]Valid Anagram: Given two strings s and t, write a function to determine if t is an anagram of s ...

  10. JDK8新特性面试

    java8:http://ifeve.com/java-8-features-tutorial/ 一.Lambda表达式和函数式接口 Lambda表达式(也叫做闭包) 它允许我们将一个函数当作方法的参 ...