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

时间:2015-05-28 01:53:18

标签: c++ shared-ptr c++14 unique-ptr

[追问this问题]

我最近对c风格数组的智能指针进行了一些处理。我最终做了推荐的事情,并使用智能指针代替向量,但在此期间,我得到了一些建议:不要使用shared_ptr<T>对象来管理最初用{{1}创建的数组因为它不会调用make_unique<T[]>而是调用delete[]

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

此代码:

delete

生成此输出:

#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[]>

来自C ++ 14标准§20.8.2.2.1pg. 571 of doc, 585 of pdf

  

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

如果我正确阅读,则意味着shared_ptr<T>对象从shared_ptr的指针和删除器构造自身。此外,我的理解(从原始问题的答案)unique_ptr类型的::pointerunique_ptr<T[]>,它应该可以转换为T*的{​​{1} }}。所以删除器应该直接从shared_ptr<T>::pointer对象复制,对吧?

我的测试是否有效,因为它实际上并不等同于T*的功能,或者是语法

unique_ptr

的良好,异常安全(和清洁)替代方案
std::make_shared<T[]>

之类的,当我无法使用Boost的shared array并希望避免在我的代码中包含std::shared_ptr<T> mySharedArray = std::make_unique<T[]>(16); std::shared_ptr<T> mysharedArray(new T[16], [](T* ptr){delete[] ptr;}); 标题时?

1 个答案:

答案 0 :(得分:6)

是的,您的例子有效,原因就在于您所说的理由。 unique_ptr::pointerint *,您试图将其所有权转移给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获取与上一行相同的删除器。