从 unique_ptr 初始化shared_ptr

2023-11-23

[后续this问题]

最近我一直在处理一些指向 C 风格数组的智能指针。我最终做了推荐的事情并使用指向向量的智能指针代替,但在那段时间,我得到了一些建议:不要使用shared_ptr<T>管理最初使用的数组的对象make_unique<T[]>因为它不会打电话delete[]反而delete.

这对我来说似乎不合逻辑,我检查了两者Coliru和标准:


这段代码:

#include <iostream>
#include <memory>

int main()
{
    std::cout << "start!\n";
    auto customArrayAllocator = [](unsigned int num){
        std::cout << "custom array allocator\n";
        return new int[num];
    };

    std::cout << "allocator constructed\n";

    auto customArrayDeleter = [](int *ptr){
        std::cout << "custom array deleter\n";
        delete[] ptr;
    };

    std::cout << "deleter constructed\n";

    std::unique_ptr<int[], decltype(customArrayDeleter)>
        myUnique(customArrayAllocator(4), customArrayDeleter);

    std::cout << "unique_ptr constructed\n";

    std::shared_ptr<int>
        myShared = std::move(myUnique);

    std::cout << "shared_ptr constructed\n";
}

产生这个输出:

start!
allocator constructed
deleter constructed
custom array allocator
unique_ptr constructed
shared_ptr constructed
custom array deleter

这似乎表明unique_ptr<T[]>的删除器被传递给shared_ptr<T>,正如我所料。


来自 C++14 标准 § 20.8.2.2.1第 页571 文档,585 pdf

模板shared_ptr(unique_ptr&& r);
Remark:此构造函数不应参与重载决策,除非 unique_ptr::pointer 可转换为 T*。
Effects:当D不是引用类型时,相当于shared_ptr(r.release(), r.get_deleter()), 否则shared_ptr(r.release(), ref(r.get_deleter()))。
异常安全:如果抛出异常,构造函数没有任何作用。

如果我没理解错的话,这意味着shared_ptr对象从指针和删除器构造自身unique_ptr。此外,据我了解(根据原始问题的答案)::pointer类型unique_ptr<T[]> is T*,这应该可以转换为shared_ptr<T>::pointer's T*。所以删除器应该直接从unique_ptr对象,对吗?


我的测试之所以有效,是因为它实际上并不等同于std::make_shared<T[]>,或者是语法

std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);

一个良好的、异常安全(且更清洁)的替代品

std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;});

等等,当我无法使用 Boost 时共享数组并希望避免包括vector or the array标题与我的代码?


是的,由于您所陈述的原因,您的示例是有效的。unique_ptr::pointer is int *,并且您试图将其所有权传递给shared_ptr<int>,因此您列出的转换构造函数将参与重载决策,并将制作删除器的副本(std::default_delete<int[]>)因为它不是引用类型。

所以以下是有效的,并且会调用delete[]当。。。的时候shared_ptr引用计数变为零

std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16);

除了您显示的 lambda 之外,另一种编写方法是

std::shared_ptr<T> mySharedArray(new T[16], std::default_delete<int[]>());

这将导致mySharedArray获取与上一行相同的删除器。

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

从 unique_ptr 初始化shared_ptr 的相关文章

  • JQuery、ASCX 和 webmethods 似乎不起作用

    我有一个级联下拉列表 其中 3 个 类型 类别和子类别 首先类型负载 然后选择类型 类别负载以及选择类别 子类别负载 我还有 2 个按钮 添加类别 和 添加子类别 单击这些按钮后 我调用 JQuery 模态表单来添加它们 我在代码后面使用
  • 如何有效地测试action是否用属性(AuthorizeAttribute)修饰?

    我正在使用 MVC 并且有一种情况OnActionExecuting 我需要确定即将执行的Action方法是否用属性修饰 AuthorizeAttribute尤其 我不是问授权是否成功 失败 而是问该方法是否需要授权 对于非 MVC 人员
  • 使用 R.Net 版本 1.5.5 创建 REngine 实例

    我正在尝试创建一个 Hello World 示例R Language using R Net版本1 5 5 从 NuGet 加载 不幸的是 我见过的在线示例都不起作用 这就是我所做的 已安装Microsoft R Open 3 2 4 增强
  • 不要覆盖 Azure Blob 存储

    我有一种将文件添加到 Azure Blob 存储的方法 问题是我试图指定一个条件 在该条件下它不会覆盖 blob 而只是添加到其中 我正在尝试使用参数访问条件 但是 VS 说这个方法不能采用两个参数 async void archiveNe
  • 有什么办法可以让这个 C# 代码更快吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在读取一个大文件 X12 并解析其中的信息 我有两个瓶颈功能 我似乎无法解决 read line 和 get element 有什
  • 缓存友好的矩阵移位功能

    我想将二维方阵的第一行移到最后一行 所以如果我有一个像A这样的矩阵 我想要得到B 我可以使用两个简单的 for 循环来做到这一点 例如 void shift int M int N int A M N int i j temp for i
  • 从 C# 访问 COM vtable

    C 中有没有办法访问 COM 对象的虚拟方法表以获取函数的地址 经过大量搜索和拼凑不同的部分解决方案后 我弄清楚了如何做到这一点 首先 您需要为您尝试访问的对象定义 COM 组件类 ComImport Guid InterfaceType
  • 增强缓冲区调用后丢失自定义点类型的数据

    我有我自己的观点 class LocationWayPoint public latlong container location WORD index PWeakBasicStation station namespace boost n
  • ICSharpCode.Decompiler + Mono.Cecil -> 如何为单个方法生成代码?

    我可以使用 Mono Cecil 和 ICSharpCode Decompiler 生成类型或程序集的代码 但是 如果我尝试为单个方法生成代码 我将收到错误 对象引用未设置为对象的实例 你们能给我任何关于这个的提示吗 提前感谢您的所有帮助
  • 使用 C# 启动 Outlook

    我可以让 C 在代码中启动 Outlook 吗 在 VB6 中 我们使用对象 Outlook Application 并编写 Set oOutlook CreateObject Outlook Application Set oNameSp
  • 使用 Rhino Mocks 模拟集合

    所以我猜这是很多人想做的事情 模拟集合 过去我用 Rhino 做过这样的事情 var col mock MockRepository GenerateMock
  • 调用 Console.ReadLine() 的方法的 C# 单元测试

    我想为名为的类的成员函数创建一个单元测试ScoreBoard它存储了一场比赛中排名前五的球员 问题是我为 SignInScoreBoard 正在呼叫Console ReadLine 这样用户就可以输入他们的名字 public void Si
  • 使用 System.Windows.Forms.Timer.Start()/Stop() 与 Enabled = true/false

    假设我们在 Net 应用程序中使用 System Windows Forms Timer 在计时器上使用 Start 和 Stop 方法与使用 Enabled 属性之间有什么有意义的区别吗 例如 如果我们希望在进行某些处理时暂停计时器 我们
  • 以编程方式将 UserControl 从 ContentControl 移动到另一个 ContentControl

    在 WPF 应用程序中 我想在代码中将 UserControl 从 ContentControl 移动到另一个控件 myContentControl2 Content myUserControl 在这种情况下我得到一个错误 指定的元素已经是
  • 如何在不加载到内存的情况下对大型 csv 文件进行排序

    我有 20GB csv 文件 如下所示 CallId MessageNo Information Number 1000 1 a 2 99 2 bs 3 1000 3 g 4 66 2 a 3 20 16 3 b 1000 7 c 4 99
  • 通过 C++ 标头在 C++ 和 C# 中使用枚举

    我有一个用 C 编写的服务器 位于命名管道的末端 嗯 提供服务 可以发送到服务器的命令在位于头文件中的枚举中定义 enum e doThing1 e doThing2 e doLastThing 所需枚举的值被放入发送到服务器的消息的第一个
  • 如何同时正确使用管道和信号?

    我有 2 个孩子 我想将信号从孩子发送到父母 并将答案 随机数 为什么 为什么不 命名管道从父母发送到每个孩子 我有这个代码 include
  • 您可以从 AuthorizeAttribute 返回 HTTP 响应而不引发异常吗?

    我在各种控制器上使用 AuthorizeAttribute 可能需要根据请求本身的某些属性返回 403 或 429 请求过多 我完全在自定义 OnAuthorization 实现中实现了它 然后在必要时抛出一个带有适当响应代码的新 Http
  • 即使没有任何转换,也违反了 C 中的严格别名?

    How can i and u i在此代码中打印不同的数字 即使i定义为int i u i 我只能假设我在这里触发了 UB 但我不知道具体是如何触发的 ideone演示 http ideone com Gcv5Xm如果我选择 C 作为语言
  • 从 C# 应用程序调用 ASP.net Web 服务

    我有个问题 我如何调用 Web 服务并从 C 桌面应用程序获取结果 我正在制作一个桌面应用程序 我希望它能够连接到我的在线 ASP net Web 服务 这怎么可能 在 解决方案资源管理器 中 右键单击项目节点并选择 添加 Service参

随机推荐

  • 在 foreach 循环内手动增加枚举器

    我在 foreach 循环内有一个嵌套的 while 循环 我想在满足特定条件时无限期地推进枚举器 为此 我尝试将枚举器转换为 IEnumerator 如果它位于 foreach 循环中 则必须如此 然后在转换的对象上调用 MoveNext
  • 网络编程:是否维护套接字?

    我目前正在将 API 从 C 转换为具有网络组件的 Java C 版本似乎在使用其类期间保持输入和输出流以及套接字打开 它是否正确 记住应用程序根据用户输入发送命令和接收事件 为每个 消息 打开一个新的套接字流是否更明智 我正在维护一个 S
  • 如何在 JavaScript 中取消移动或添加到参数对象的开头

    我刚刚学会了弹出第一个元素的约定arguments array 我还了解到这实际上是一个Object 现在我需要做相反的事情 我需要使用一个unshift将值添加到开头的操作arguments数组 或Object就像一个数组 这可能吗 我试
  • R 中 stri_detect_regex 错误

    我收到此错误 stri detect regex string pattern opts regex opts pattern 中的错误 正则表达式模式中的括号嵌套不正确 U REGEX MISMATCHED PAREN 当我运行代码时 f
  • 画布中的矩形尺寸错误

    我正在实现一个颜色选择器 渲染有问题 当我打电话时c fillRect 0 0 100 80 该矩形的大小是 103x42 像素 而不是 100x80 这里有什么问题吗 此外 矩形是抗锯齿的 我是否需要将位置偏移 0 5 0 5 以避免 A
  • 线性 SVM 模型的权重(在 R 中)?

    Using kernlab我用如下代码训练了一个模型 my model lt ksvm result f1 f2 f3 data gold kernel vanilladot 由于它是一个线性模型 我更喜欢在运行时将分数计算为特征值的简单加
  • CXF/ JAX-RS :从拦截器返回自定义响应

    当REST调用过程中发生异常时 我们需要返回自定义的错误代码和错误消息 我们创建了一个异常映射器提供程序 它适用于应用程序代码中的异常 但是 当 CXF 代码发生异常时 例如 我编写的 CustomValidationInterceptor
  • 如何在可变参数模板中匹配空参数包

    我有代码 template
  • 在 Xamarin.Forms 中使用 Thread.Sleep

    我想执行以下操作 MainPage new ContentPage Content new StackLayout Children new Button Text Thread Sleep Command new Command gt T
  • 确定 nvcc 需要哪些 gencode(compute_、arch_)值 - 在 CMake 中

    我使用 CMake 作为我的代码的构建系统 其中涉及 CUDA 我正在考虑将决定哪个任务自动化compute XX and arch XX我需要传递给我的 nvcc 以便为我当前计算机上的 GPU 进行编译 有没有办法做到这一点 使用 NV
  • 如何在 jqgrid 中添加新的按钮/图像列

    我在 ASP net MVC Web 应用程序中使用 JQgrid 我可以使用以下命令添加名为编辑的新按钮列formatters 但是 问题是我无法获取单击按钮的行中的列的值 例如 如果我单击第四行上的按钮编辑 新添加 我将需要获取该特定行
  • 在 Azure 存储上托管 SQLite DB?

    我需要在 Azure 上托管一个 SQLite 数据库 该数据库将在多个 Web 应用程序之间共享 我唯一的选择似乎是 Azure Blob 或文件存储 因为它们摆脱了提供在 Web 实例之间共享的专用存储的 Azure 网站 但是 似乎没
  • 如何条件正则表达式

    我想要一个正则表达式 如果它有 3 个实例 它就做一件事 在字符串中 如果它有超过 3 个实例 则为其他内容 例如 aaa bbb ccc ddd one part of the regex aaa bbb ccc ddd eee the
  • 创建 R 包时包含 jar 文件

    我创建了一个 R 框架包 lib jarFileHere jar R r code file R The r code file R尝试引用一个类文件jar文件在这里 jar library rJava library rjson onLo
  • 如何从 Blob 转到 ArrayBuffer

    我正在研究 Blob 我注意到当你有 ArrayBuffer 时 你可以轻松地将其转换为 Blob 如下所示 var dataView new DataView arrayBuffer var blob new Blob dataView
  • 如何在Go中调用linux共享库函数?

    我有一个 so 文件 我想在 Go 代码中调用其函数 我该如何去做呢 我已经阅读了 cgo 和 syscall 包 它们接近我想要的 但我没有看到任何可以调用 so 文件中的函数的地方 我想完全实现 ctypes 包在 Python 中的功
  • 如何在添加数组之前检查特定对象是否已存在于数组中[重复]

    这个问题在这里已经有答案了 我有这个数组 name Olvier id 123 name Olvier id 124 现在我的目标是防止再次将相同的对象添加到数组中 name Olvier id 123 有没有一种方法可以做到这一点 如果您
  • document.getElementsByTagName("*") 或 document.all

    document getElementsByTagName 适用于 IE Firefox Opera 但不适用于 Chrome 和 Safari document all适用于 IE Chrome Safari 但不适用于 Firefox
  • 如何在 MVC 中实现工作单元:职责

    谁有责任 谁负责启动和完成 MVC 架构中的工作单元 这不是控制者的责任 它违反了SRP 控制器根本不应该知道 UoW 在 Web 中 通常对服务器的每个请求使用一个 UoW 在这种情况下 UoW 应在请求结束时进行处理 并在请求开始后的某
  • 从 unique_ptr 初始化shared_ptr

    后续this问题 最近我一直在处理一些指向 C 风格数组的智能指针 我最终做了推荐的事情并使用指向向量的智能指针代替 但在那段时间 我得到了一些建议 不要使用shared ptr