为什么std :: shared_ptr <t> = std :: unique_ptr <t []>编译,而std :: shared_ptr <t []> = std :: unique_ptr <t []>没有?

时间:2015-05-12 16:39:43

标签: c++ stl g++ c++14

我使用以下输入命令在Coliru中探讨了这个主题:

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

可以找到here的测试,但我已经发布了以下代码。我在我的示例中使用了int,因为它是基本类型。

#include <iostream>
#include <memory>

struct Foo{
    Foo() :
    a_{0}, b_{1}, c_{-1}, combination_{0.5} {}

    int
        a_,
        b_,
        c_;
    double
        combination_;
};

int main()
{
    //int
    //    *unManagedArray = new int[16];
    std::unique_ptr<int[]>
        uniqueArrayOrigin = std::make_unique<int[]>(16);
    std::shared_ptr<int>
            // works but needs call to new
    //  sharedSingleTest{unManagedArray, std::default_delete<int[]>{}}; 
            // works, does not require call to new
        sharedSingleUnique = std::make_unique<int[]>(16);       
            // compilation error (conversion to non-scalar type)
    //  sharedSingleDerived = uniqueArrayOrigin;                

    //  std::shared_ptr<int[]>
                // compilation errors
    //      sharedArrayTest{unManagedArray, std::default_delete<int[]>{}};
                // compilation error (conversion to non-scalar type)
    //      sharedArrayUnique = std::make_unique<int[]>(16);
                // compilation error (conversion to non-scalar type)
    //      sharedArrayDerived = uniqueArrayOrigin;

    std::shared_ptr<Foo>
            // works: specified overload of operator= for shared_ptr
        nonArrayTest = std::make_unique<Foo>(); 

    std::cout << "done!\n";
}

我已经在SO上寻找答案,但只是referencesstd::shared_ptr执行operator=而没有专业化,而这主要是因为没有人费心去提出适当的建议关于这个问题的标准委员会。

我很好奇,因为我会在cppreference上解释T[]std::shared_ptr<T[]>.operator=(std::unique_ptr<T[], Deleter>&&)的第4次重载,以表明此类语法合法 - T[]std::shared_ptr相同毕竟,无论std::make_unique<T[]>的数组类型的特化状态如何,都要输入。

此外,这种语法似乎只适用于std::unique_ptr<T[]>的产品,而不是一个独特的指针对象,这违背了我对该主题的理解 - 不应该调用实际上是相同的,尽管一个移动现有对象,另一个移动刚刚创建的对象?我希望它们之间的唯一区别是在第一种情况下函数调用之后的无效shared_ptr

作为旁注,我假设由于有一种方法可以将动态分配的数组构建到new中,而不需要使用new T[N],我应该更喜欢它。和operator=的异常不安全调用?

TL; DR:

  1. std::shared_ptr<T[]>std::unique_ptr<T[]>T[]之间根本不起作用,但我希望它可以正常工作。为什么?
  2. 如果有的话,我希望从Toperator=的类型转换成为唯一和共享指针之间的编译错误的来源。为什么这样做?
  3. std::shared_ptr<T>适用于std::make_unique<T[]>std::unique_ptr<T[]>,但不适用operator= std::make_unique<T[]>(N)。为什么?
  4. 我正确地假设在需要动态分配的共享数组的情况下,但我不想使用boost或vector(下面的原因)我应该调用manage_reportUserPermissions
  5. 为什么我不使用?

    • 提升:我公司尚未批准使用,我不知道何时或是否会获得批准使用它。
    • 数组:我必须在运行时确定此数组的大小。
    • 向量:我正在研究一个实时信号处理系统,并希望避免额外的指针取消引用。我还试图避免在我的头文件中包含无关的库(这是用于读写子系统之间的通信)但是,我最终选择优化它,如果它很重要(过早优化......)并咬紧牙关。但问题仍然存在。

1 个答案:

答案 0 :(得分:5)

§20.8.2.2.1/ 28:

template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); 
     

备注:此构造函数不应参与重载解析   除非unique_ptr<Y, D>::pointer可转换为T*

但是,unique_ptr<U[]>::pointer实际上是U*,而shared_ptr<U[]>的{​​{1}}是T*;并且U(*)[]无法转换为U*,因此永远不会考虑重载。