引入

shared_ptr 是c++为了提高安全性而添加的智能指针,方便了内存管理。

特点

shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象。这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。这在非环形数据结构中防止资源泄露很有帮助。使得指针可以共享对象,并且不用考虑内存泄漏问题

shared_ptr 可以支持普通指针的所有操作,完全可以像操作普通指针一样操作智能指针。
shared_ptr 可以通过三种方式得到(拷贝初始化,定义delete操作的方式不在罗列,只讨论初始化指针所指对象来源):
1.通过一个指向堆上申请的空间的指针初始化(切记不要用栈上的指针,否则,当智能指针全部释放控制权(栈中的对象离开作用域本身就会析构一次),将会析构对象,导致出错)
2.通过make_shared函数得到
3.通过另外一个智能指针初始化

    int *a = new int(8);std::shared_ptr<int> p1(a);auto b = std::make_shared<int>(2);auto c(b);

注意事项

1. 使用原生指针多次初始化

class Base
{
public:Base() {printf("con\n");}~Base() {printf("decon\n");}
};int main()
{Base *a = new Base();std::shared_ptr<Base> p1(a);std::shared_ptr<Base> p2(a);return 0;
}

这段代码,导致调用一次构造函数,两次析构函数

2. 使用一个 shared_ptr 的 get() 初始化另一个 shared_ptr

    Base *a = new Base();std::shared_ptr<Base> p1(a);std::shared_ptr<Base> p2(p1.get());

cppreference 指明这是未定义行为

3. 使用 shared_ptr 包装 this 指针

class Base
{
public:Base() {printf("con\n");}~Base() {printf("decon\n");}std::shared_ptr<Base> sget() {return std::shared_ptr<Base>(this);}
};int main()
{Base b;std::shared_ptr<Base> p = b.sget();return 0;
}

这会调用两次析构函数。一次是b对象析构时,一次是智能指针销毁时

正确的使用方法是:

class Base : public std::enable_shared_from_this<Base>
{
public:Base() {printf("con\n");}~Base() {printf("decon\n");}std::shared_ptr<Base> sget() {return shared_from_this();}
};int main()
{std::shared_ptr<Base> b = std::make_shared<Base>();std::shared_ptr<Base> a = b->sget();return 0;
}

enable_shared_from_this 能让其一个对象(假设其名为 t ,且已被一个 std::shared_ptr 对象 pt 管理)安全地生成其他额外的 std::shared_ptr 实例(假设名为 pt1, pt2, ... ) ,它们与 pt 共享对象 t 的所有权。

4. shared_ptr 包装数组

shared_ptr 不能直接包装数组,需要指定数组的析构函数。不过 shared_ptr 不支持取下标操,unique_ptr 是支持的

class Base
{
public:Base() {printf("con\n");}~Base() {printf("decon\n");}
};int main()
{std::shared_ptr<Base> a(new Base[2], [] (Base* p) {delete[] p;});return 0;
}

5. 循环引用

class A;
class B;using sa = std::shared_ptr<A>;
using sb = std::shared_ptr<B>;class A
{
public:A() {printf("A con\n");}~A() {printf("A decon\n");}sb b_;
};class B
{
public:B() {printf("B con\n");}~B() {printf("B decon\n");}sa a_;
};int main(int argc, char const *argv[])
{sa a(new A);sb b(new B);a->b_ = b;b->a_ = a;return 0;
}

对象 a 和 b 都未被析构

正确的方法是使用 weak_ptr 代替 shared_ptr

class A;
class B;using sa = std::shared_ptr<A>;
using sb = std::shared_ptr<B>;class A
{
public:A() {printf("A con\n");}~A() {printf("A decon\n");}std::weak_ptr<B> b_;
};class B
{
public:B() {printf("B con\n");}~B() {printf("B decon\n");}std::weak_ptr<A> a_;
};int main(int argc, char const *argv[])
{sa a(new A);sb b(new B);a->b_ = b;b->a_ = a;return 0;
}

6. 多线程中使用 shared_ptr

shared_ptr的引用计数本身是安全且无锁的,但对象的读写则不是,因为 shared_ptr 有两个数据成员,读写操作不能原子化。shared_ptr 的线程安全级别和内建类型、标准库容器、std::string 一样,即:

  • 一个 shared_ptr 对象实体可被多个线程同时读取
  • 两个 shared_ptr 对象实体可以被两个线程同时写入,“析构”算写操作
  • 如果要从多个线程读写同一个 shared_ptr 对象,那么需要加锁

转载于:https://www.cnblogs.com/zuofaqi/p/11222144.html

shared_ptr 用法相关推荐

  1. boost::shared_ptr用法测试程序

    boost::shared_ptr用法测试程序 实现功能 C++实现代码 实现功能 boost::shared_ptr用法测试程序 C++实现代码 #include <boost/config. ...

  2. C++ make_shared() shared_ptr()用法(七)

    1.make_shared.shared_ptr用法   shared_ptr很好地消除了显式的delete调用,如果读者掌握了它的用法,可以肯定delete将会在你的编程字典中彻底消失 .但这还不够 ...

  3. C++ shared_ptr用法、简析、案例

    shared_ptr用法 1 shared_ptr简介 2 shared_ptr案例 2.1 reset()的理解 2.2 make_shared的理解 2.3 shared_ptr中的指针转型问题 ...

  4. C++ make_shared() shared_ptr()用法

    shared_ptr很好地消除了显式的delete调用,如果读者掌握了它的用法,可以肯定delete将会在你的编程字典中彻底消失 .但这还不够,因为shared_ptr的构造还需要new调用,这导致了 ...

  5. C++智能指针shared_ptr用法

    目录 shared_ptr功能介绍 shared_ptr提供的接口 shared_ptr初始化 shared_ptr管理指针的构造和析构 shared_ptr获取原始指针 shared_ptr的线程安 ...

  6. shared_ptr和weak_ptr使用介绍

    文章目录 1 shared_ptr使用介绍 1.1 shared_ptr使用介绍 1.2 shared_ptr的使用陷阱 2 weak_ptr使用简介 1 shared_ptr使用介绍 1.1 sha ...

  7. shared_ptr使用场景、陷阱、性能分析,使用建议

    1.std::shared_ptr使用场景 #include <iostream> #include <memory>using namespace std;shared_pt ...

  8. C++:shared_ptr以及一些常见的问题

    本文以vs2010中的std::tr1::shared_ptr为例,说明shared_ptr用法. 1.基本功能 shared_ptr提供了一个管理内存的简单有效的方法.shared_ptr能在以下方 ...

  9. Effective C++ 学习笔记

    基于此文档 http://wenku.baidu.com/view/ef989106e87101f69e3195db.html 条款13:以对象管理资源 目标:为确保资源被释放 1.获得资源后立即放进 ...

最新文章

  1. 初学C++正则表达式(regex)
  2. 关于java包_关于Java包
  3. java+jsp+sqlserver 2008+Tomcat实现一个简单的搜索引擎
  4. 大数据面试题总结(附答案)
  5. oracle 0.1变.1,Oracle在12.1.0.2开始改变了补丁策略
  6. 在回传时保持滚动位置
  7. Kali Linux渗透测试——WEB渗透(二)
  8. 手机蓝牙串口的调试助手demo实现
  9. m0单片机io口_51单片机50个例程代码
  10. Step 1: 盲打第三天
  11. 图书isbn批量生成一维条码
  12. 37 岁老码农找工作,现身说法...
  13. IEEE802模型与协议标准
  14. 细数中国大学里的30个怪现状
  15. 计算机文件一点右键就内存突增,电脑内存占用忽然升高怎么解决
  16. 如何在线批量进行PDF拆分
  17. 判断链表是否为【回文结构】
  18. 关于module ‘datetime‘ has no attribute ‘now‘报错解决方案
  19. C#,.net使用特性类,将json转为实体时验证字段
  20. 美国第一个设置计算机的学校,美国计算机专业院校

热门文章

  1. html图标点击转换颜色,PNG格式小图标的CSS任意颜色赋色技术_html/css_WEB-ITnose
  2. c 路径 空格 参数_好听的炫舞名字空格最新_好听的炫舞名字空格2020
  3. ar 微信小程序_微信AR玩法支持实现后,微信小程序会有想象空间吗?
  4. java ee核心技术与应用_Java EE核心技术与应用(全面覆盖Java EE 6) 郝玉龙等著 pdf扫描版[103MB]...
  5. mysql千万级大数据SQL查询优化
  6. 【Deep Learning笔记】前馈神经网络和BP算法
  7. python【蓝桥杯vip练习题库】ADV-120 6-17复数四则运算
  8. 统计元音(格式控制)
  9. 博途数据类型wstring怎么用_如何在STEP 7 (TIA 博途)中使用“用户定义数据类型” (UDTS)...
  10. 计算机控制技术曹立学答案,高等学校电子与电气工程及自动化专业十二五规划教材:计算机控制技术...