共享指针

管理指针的存储,提供有限的垃圾回收工具,并可能与其他对象共享该管理。

shared_ptr类型的对象都能够获得指针的所有权并共享该所有权:一旦它们获得所有权,当最后一个所有者释放该所有权时,指针的所有者组就负责删除该所有者。

shared_ptr对象在自身被销毁后,或者一旦其值因赋值操作或显式调用 shared_ptr::reset 而发生更改,就会释放其共同拥有的对象的所有权。一旦通过指针共享所有权的所有shared_ptr对象都释放了此所有权,则将删除托管对象(通常通过调用 ::delete,但在构造时可能会指定不同的删除程序)。

shared_ptr对象只能通过复制其值来共享所有权:如果从同一个(非shared_ptr)指针构造(或创建)两个shared_ptr,则它们都将拥有该指针而不共享它,当其中一个对象释放它(删除其托管对象)并使另一个指向无效位置时,会导致潜在的访问问题。

此外,shared_ptr对象可以通过指针共享所有权,同时指向另一个对象。此功能称为别名,通常用于指向成员对象,同时拥有它们所属的对象。因此,shared_ptr可能与两个指针相关:

  • 存储的指针,它是它所指向的指针,也是它使用运算符* 取消引用的指针。
  • 拥有的指针(可能是共享的),这是所有权组负责在某个时刻删除的指针,并且它被视为一种用途。

通常,存储的指针和拥有的指针引用同一对象,但别名shared_ptr对象(使用别名构造函数及其副本构造的对象)可能引用不同的对象。

不拥有任何指针的shared_ptr称为空shared_ptr。不指向任何对象的shared_ptr称为 null shared_ptr,不应取消引用。请注意,空shared_ptr不一定是 null shared_ptr,null shared_ptr不一定是空shared_ptr。

shared_ptr对象通过运算符 * 和 -> 提供对它们所指向的对象的访问,从而复制有限的指针功能。出于安全原因,它们不支持指针算术。

相关类weak_ptr能够与shared_ptr对象共享指针,而无需拥有它们。

成员函数

	(构造函数)构造shared_ptr(公共成员函数)
(析构函数)销毁shared_ptr(公共成员函数)
operator= shared_ptr赋值(公共成员函数)
swap 交换内容(公共成员函数)
reset 重置指针(公共成员函数)
get 获取指针(公共成员函数)
operator* 取消引用对象(公共成员函数)
operator-> 取消引用对象成员(公共成员函数)
operator[] (C++17)提供到被存储数组的带下标访问(公开成员函数)
use_count 返回计数(公共成员函数)
unique(C++20前) 检查是否唯一(公共成员函数)
operator bool 检查是否不为空(公共成员函数)
owner_before 基于所有者的共享指针排序(公共成员函数模板) 非成员函数
swap 交换shared_ptr对象的内容(函数模板)
relational operators 关系运算符 ==, !=, <, <=, >, >= (函数模板 )
ostream operator<< 将存储的指针的值输出到输出流(函数模板) 具体功能:
make_shared,make_shared_for_overwrite(C++20) 创建管理一个新对象的共享指针(函数模板)
allocate_shared,allocate_shared_for_overwrite(C++20) 创建管理一个用分配器分配的新对象的共享指针(函数模板)
static_pointer_cast,dynamic_pointer_cast,const_pointer_cast,reinterpret_pointer_cast (C++17)应用 static_cast、dynamic_cast、const_cast 或 reinterpret_cast 到被存储指针(函数模板)
get_deleter 返回指定类型中的删除器,若其拥有(函数模板)

cpp

#include <utility>
#include <cstddef> class ref_count
{
public:
int use_count() const noexcept { return count_; }
void inc_ref() noexcept { ++count_; }
int dec_ref() noexcept { return --count_; } private:
int count_{1};
}; template <typename T>
class Shared_ptr
{
public:
constexpr Shared_ptr() noexcept = default;
constexpr Shared_ptr(nullptr_t) noexcept : Shared_ptr() {}
explicit Shared_ptr(T *ptr) : ptr_{ptr}
{
if (ptr_ != nullptr)
{
rep_ = new ref_count{};
}
}
Shared_ptr(const Shared_ptr &rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_}
{
if (ptr_ != nullptr)
{
rep_->inc_ref();
}
}
Shared_ptr(Shared_ptr &&rhs) noexcept : ptr_{rhs.ptr_}, rep_{rhs.rep_}
{
rhs.ptr_ = nullptr;
rhs.rep_ = nullptr;
}
~Shared_ptr() noexcept
{
if (rep_ != nullptr && rep_->dec_ref() == 0)
{
delete ptr_;
delete rep_;
}
} Shared_ptr &operator=(const Shared_ptr &rhs)
{
Shared_ptr{rhs}.swap(*this);
return *this;
}
Shared_ptr &operator=(Shared_ptr &&rhs)
{
Shared_ptr{std::move(rhs)}.swap(*this);
return *this;
}
void reset() noexcept
{
Shared_ptr{}.swap(*this);
}
void reset(nullptr_t) noexcept
{
reset();
}
void reset(T *ptr)
{
Shared_ptr{ptr}.swap(*this);
} void swap(Shared_ptr &rhs) noexcept
{
std::swap(ptr_, rhs.ptr_);
std::swap(rep_, rhs.rep_);
}
T *get() const noexcept
{
return ptr_;
} long use_count() const noexcept
{
return rep_ == nullptr ? 0 : rep_->use_count();
}
bool unique() const noexcept
{
return rep_->use_count() == 1;
} T &operator*() const noexcept
{
return *ptr_;
}
T &operator->() const noexcept
{
return ptr_;
} explicit operator bool() const noexcept
{
return static_cast<bool>(ptr_);
} private:
T *ptr_{nullptr};
ref_count *rep_{nullptr};
}; template <typename T, typename... Args>
auto make_Shared(Args &&...args)
{
return Shared_ptr<T>{new T(std::forward(args)...)};
}

C++ 简单实现shared_ptr的更多相关文章

  1. 简单的shared_ptr实现

    RT,代码参考了STL中shard_ptr的实现,基本原理是引用计数,利用Ref_cnt类来管理内存,在shared_ptr创建时创建,此后shared_ptr仅是在拷贝复制析构的过程中对引用进行修改 ...

  2. 实现一个简单的shared_ptr

    翻看以前的代码的时候发现一个shared_ptr的简单实现. 我记得是网上的一篇例子(好像改了一点),但是又懒得找出处了 ╮(╯▽╰)╭. 觉得这份代码足以用来初步了解shared_ptr的实现了. ...

  3. shared_ptr / weak_ptr 代码片段

    参考<<Boost程序库完全开放指南>> shared_ptr  类摘要(只列出了常用的部分)和相关说明 template <class T> class shar ...

  4. 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr

    什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...

  5. C++内存管理之shared_ptr

     ----------------------------------------shared_ptr--------------------------------------- 引子 c++中动态 ...

  6. auto_ptr和shared_ptr

    <Effective C++>在资源管理一节提到了智能指针,智能指针中最著名的当属auto_ptr和shared_ptr.本文主要研究两者的实现. auto_ptr的实现: templat ...

  7. 异常处理与MiniDump详解(2) 智能指针与C++异常

    write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 讨论新闻组及文件 一.   综述 <异常处理与MiniDump详解(1) C++异常>稍 ...

  8. 使用TR1的智能指针

    作为C++程序员,在没有智能指针,手动管理内存的蛮荒岁月里,可以说是暗无天日,痛苦异常.直到上帝说,还是要有光,于是智能指针进了标准.C++码农的日子总算好起来了. 虽然一直鄙视着没有显式指针的语言, ...

  9. shared_ptr的简单实现

    前面讲到auto_ptr有个很大的缺陷就是所有权的转移,就是一个对象的内存块只能被一个智能指针对象所拥有.但我们有些时候希望共用那个内存块.于是C++ 11标准中有了shared_ptr这样的智能指针 ...

  10. shared_ptr和多线程

    前一篇文章写得实在太挫,重新来一篇. 多线程环境下生命周期的管理 多线程环境下,跨线程对象的生命周期管理会有什么挑战?我们拿生产者消费者模型来讨论这个问题. 实现一个简单的用于生产者消费者模型的队列 ...

随机推荐

  1. win32 - IFolderView2::GetCurrentFolderFlags的使用

    网上关于IFolderView2接口调用的示例有点少. 下面的例子是将桌面的图标隐藏起来,使用了FWF_NOICONS样式. #include <ShlObj.h> // Shell AP ...

  2. win32 - 写入安全日志(AuthzRegisterSecurityEventSource和AuthzReportSecurityEvent)

    微软文档介绍说, 安全日志在其他两个重要方面与其他日志不同.首先,在默认配置中,它受到强大的访问控制列表(ACL)和特权检查的保护,这将可以读取其内容的个人的范围限制为本地系统,管理员和安全特权的持有 ...

  3. win32 - 使用LookupAccountName查找SID

    可以使用LookupAccountNameA获取sid. LookupAccountName函数接受系统名称和帐户作为输入.它检索该帐户的安全标识符(SID)以及在其上找到该帐户的域的名称. 使用此a ...

  4. win32 - 在cmd中禁用进程权限

    C:\Users\path>whoami /priv 在cmd中输入whoami /priv后将获得当前令牌(标准用户)的权限. C:\Users\path>tasklist /v /fo ...

  5. 好用的OCR文本识别工具

    之所以会用到OCR工具,是因为在看一些扫描版的PDF文档时,有时候需要复制粘贴一些文字,特别是技术性文档,对于一些命令或者代码片段需要复制出来执行验证. 网络上有许多推荐OCR工具的文章,但是大多数都 ...

  6. typing模块中Protocol协议的使用

    说明 在 Python 的 typing 模块中,Protocol 是一个用于定义协议(Protocol)的类. 协议是一种形式化的接口,定义了一组方法或属性的规范,而不关心具体的实现.Protoco ...

  7. defaultdict高级用法

    说明 defaultdict数据结构允许调用者提供一个函数,用来在键名缺失的情况下,创建与这个 键对应的值.只要字典发现调用者想要访问的键不存在,就会触发这个函数,以返回应该 与键相关联的默认值 下面 ...

  8. mac上安装vue

    安装node.js brew install nodejs node -v #查看版本 给nodejs模块安装目录设置访问权限 sudo chmod -R 777 /usr/local/lib/nod ...

  9. ABP模块签入GitLab后自动打包并推送到ProGet

    # 1.添加一个名为下划线的解决方案文件夹 # 2.把解决方案根目录下的几个必要的文件添加到上述文件夹下 # 3.修改NuGet.Config,添加私有NuGet服务器的网址,并配置用户名和密码: A ...

  10. DataGear 制作自适应任意屏幕尺寸的数据可视化看板

    DataGear 即支持以编写HTML.JavaScript.CSS源码的源码模式制作看板,也支持直观可见.友好快捷的可视模式制作看板. 本文将通过看板可视编辑模式提供的网格布局和样式设置功能,介绍如 ...