你能让 std::shared_ptr 管理用 new T[] 分配的数组吗?

2024-03-17

你能做一个std::shared_ptr http://en.cppreference.com/w/cpp/memory/shared_ptr指向一个数组?例如,

std::shared_ptr<int> sp(new int[10]);

如果没有,那为什么不呢?我已经知道的原因之一是不能增加/减少std::shared_ptr。因此它不能像普通的数组指针一样使用。


With C++17, shared_ptr可用于管理动态分配的数组。这shared_ptr在这种情况下,模板参数必须是T[N] or T[]。所以你可以写

shared_ptr<int[]> sp(new int[10]);

从n4659开始,[util.smartptr.shared.const] https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared.const

  template<class Y> explicit shared_ptr(Y* p);

要求: Y应该是一个完整的类型。表达方式delete[] p, when T是数组类型,或者delete p, when T不是数组类型,应具有明确定义的行为,并且不应引发异常。
...
Remarks: When T是数组类型,此构造函数不应参与重载决策,除非表达式delete[] p是格式良好的,并且T is U[N] and Y(*)[N]可转换为T*, or T is U[] and Y(*)[]可转换为T*. ...

为了支持这一点,成员类型element_type https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared#1现在定义为

using element_type = remove_extent_t<T>;

可以使用以下方式访问数组元素operator[] https://timsong-cpp.github.io/cppwp/n4659/util.smartptr.shared.obs#8

  element_type& operator[](ptrdiff_t i) const;

要求: get() != 0 && i >= 0. If T is U[N], i < N. ...
Remarks: When T不是数组类型,未指定是否声明该成员函数。如果声明了它,则未指定其返回类型是什么,但函数的声明(尽管不一定是定义)应格式良好。


C++17 之前, shared_ptr could not用于管理动态分配的数组。默认情况下,shared_ptr将会通知delete当不再有对托管对象的引用时。但是,当您分配使用new[]你需要打电话delete[], 并不是delete,释放资源。

为了正确使用shared_ptr对于数组,您必须提供自定义删除器。

template< typename T >
struct array_deleter
{
  void operator ()( T const * p)
  { 
    delete[] p; 
  }
};

创建shared_ptr如下:

std::shared_ptr<int> sp(new int[10], array_deleter<int>());

Now shared_ptr将正确调用delete[]当销毁被管理对象时。

上面的自定义删除器可以替换为

  • the std::default_delete http://en.cppreference.com/w/cpp/memory/default_delete数组类型的部分特化

    std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
    
  • lambda 表达式

    std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
    

另外,除非您确实需要共享托管对象的所有权,否则unique_ptr更适合此任务,因为它对数组类型有部分特化。

std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]

C++ 库基础扩展引入的更改

上面列出的另一种 C++17 之前的替代方案由库基础技术规范 http://en.cppreference.com/w/cpp/experimental/lib_extensions,这增强了shared_ptr允许它在拥有对象数组的情况下开箱即用。目前的草案shared_ptr可以在以下位置找到此 TS 的更改N4082 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4082.pdf。这些更改可通过std::experimental命名空间,并包含在<experimental/memory>标头。支持的一些相关更改shared_ptr对于数组是:

— 成员类型的定义element_type changes

typedef T element_type;

 typedef typename remove_extent<T>::type element_type;

- 成员operator[]正在添加中

 element_type& operator[](ptrdiff_t i) const noexcept;

- 不像unique_ptr数组的部分特化,两者shared_ptr<T[]> and shared_ptr<T[N]>将是有效的,并且两者都会导致delete[]在托管对象数组上调用。

 template<class Y> explicit shared_ptr(Y* p);

Requires: Y应该是一个完整的类型。表达方式delete[] p, when T是数组类型,或者delete p, when T不是数组类型,应格式良好,应具有明确定义的行为,并且不应引发异常。什么时候T is U[N], Y(*)[N]应可转换为T*; when T is U[], Y(*)[]应可转换为T*;否则,Y*应可转换为T*.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

你能让 std::shared_ptr 管理用 new T[] 分配的数组吗? 的相关文章

  • UTF8/UTF16 和 Base64 在编码方面有什么区别

    In c 我们可以使用下面的类来进行编码 System Text Encoding UTF8 System Text Encoding UTF16 System Text Encoding ASCII 为什么没有System Text En
  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • 如何在没有 Control.Invoke() 的情况下从后台线程修改控件属性

    最近 我们遇到了一些旧版 WinForms 应用程序 我们需要更新一些新功能 在专家测试该应用程序时 发现一些旧功能被破坏 无效的跨线程操作 现在 在您认为我是新手之前 我确实有一些 Windows 窗体应用程序的经验 我不是专家 但我认为
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的

随机推荐