从unique_ptr <T []>初始化shared_ptr <T>

锯齿状

[问题的跟进]

最近,我一直在处理指向c样式数组的智能指针。最终,我做了最后的建议,而是使用了智能的指向矢量的指针,但是在此期间,我得到了一些建议:不要使用shared_ptr<T>对象来管理最初使用的数组,make_unique<T[]>因为它不会调用delete[]而是delete

这对我来说似乎不合逻辑,我同时检查了Coliru和Standard:


这段代码:

#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[]>的Deleter已传递给shared_ptr<T>


从C ++ 14标准§20.8.2.2.1 pg。doc 571,pdf 585

模板shared_ptr(unique_ptr && r);
备注:除非unique_ptr :: pointer可转换为T *,否则此构造函数不得参与重载解析。
效果:当D不是引用类型时,等效于shared_ptr(r.release(),r.get_deleter()),否则等于shared_ptr(r.release(),ref(r.get_deleter()))。
异常安全性:如果引发异常,则构造方法无效。

如果我没看错,那意味着shared_ptr对象从的指针和删除器构造自己unique_ptr此外,根据我的理解(从对原始问题的回答),is::pointer类型应该可以转换为所以删除器应该只是从对象中复制出来的,对吗?unique_ptr<T[]>T*shared_ptr<T>::pointerT*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的共享数组并希望避免vectorarray代码中包含标头时?

普雷托里亚人

是的,由于您陈述的原因,您的示例是有效的。unique_ptr::pointerint *,并且您正尝试将其所有权传递给shared_ptr<int>,因此您列出的转换构造函数将参与重载解析,并且将复制deleter(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获得与上一行相同的删除器。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

从std :: shared_ptr <void>初始化std :: shared_ptr <T>

如何初始化std :: unique_ptr <std :: unique_ptr <T> []>?

使用boost :: shared_ptr <std :: list <T >>初始化boost :: shared_ptr <std :: vector <T >>

为什么std :: shared_ptr <T> = std :: unique_ptr <T []>可以编译,而std :: shared_ptr <T []> = std :: unique_ptr <T []>不可以编译?

std :: vector <unique_ptr <class T >>的动态初始化

从初始化列表构造std :: map <T,unique_ptr <S >>时出错

错误:没有用于初始化“std::shared_ptr<uint8_t []>”的匹配构造函数

使用std :: unique_ptr <T>&代替std :: unique_ptr <T>有什么优势吗?

为什么unique_ptr <T> ::〜unique_ptr需要定义T?

添加从unique_ptr <T>到T *的隐式转换

使用 std::unique_ptr<T>::unique_ptr` 在 Visual Studio 2013 中构建错误

在销毁原始unique_ptr之后,由unique_ptr <T> :: get()返回的指针不是nullptr。

调整大小std :: vector <std :: unique_ptr <T >>的性能

参数std :: unique_ptr <T> &&的std :: move或std :: forward

std :: unique_ptr <T>而不在堆上分配内存

在gcc 6中实现std :: unique_ptr <T []> :: reset

就释放而言,unique_ptr <T> :: operator =做什么

make_unique <T>()和unique_ptr <T>(new T)之间的区别

从shared_ptr <T>派生

std :: shared_ptr初始化

C ++模板部分专业化-最独特的是unique_ptr <t>

用于unique_ptr <T>成员的模板化通用设置器

来自T *的std :: unique_ptr <T>的构造函数背后的原因是什么?

为什么可以在寄存器中传递T *,但不能传递unique_ptr <T>?

为什么std :: unique_ptr不能隐式转换为T *和const T *?

是否需要std :: unique_ptr <T>知道T的完整定义?

如何将vector <unique_ptr <T >>复制到独立vector <T *>

不能使用std :: unique_ptr <T>且T为前向声明

shared_ptr <T>到shared_ptr <T const>,vector <T>到vector <T const>