如何返回唯一指针的数组/向量?

时间:2014-06-28 12:25:06

标签: c++ arrays c++11 vector unique-ptr

使用本机数组,std :: array和std :: vector

尝试以下代码
typedef unique_ptr<int> UPtr;

UPtr[] f() // wrong, how to return a native array?
{
    UPtr a[] = { UPtr(new int(1)), UPtr(new int(2)) };
    return std::move(a);
}

std::array<UPtr, 2> g()
{
    std::array<UPtr, 2> a = { UPtr(new int(1)), UPtr(new int(2)) }; // compile ok but run wrong, 1 and 2 are not assigned
    return std::move(a); // wrong, call a deleted function
}

std::vector<UPtr> h()
{
    std::vector<UPtr> a = { UPtr(new int(1)), UPtr(new int(2)) }; // wrong, call a deleted function
    return std::move(a);
}

全部失败。这里有很多问题。如何修复它们?非常感谢。

1 个答案:

答案 0 :(得分:2)

由于std:array<T, N>是一个聚合,因此它是成员允许的可复制或可移动的。这意味着一切都应该按预期工作。实际上,下面的代码可以很好地编译Clang,libc ++和-std=c++1y(后者为std::make_unique选择),如果你拼出make_unique调用,也可以在GCC 4.8中使用libstdc ++:

#include <memory>
#include <array>

std::array<std::unique_ptr<int>, 2> f()
{
    std::array<std::unique_ptr<int>, 2> a = { {
        std::make_unique<int>(1), std::make_unique<int>(2) } };
    return a;
}

#include <iostream>

int main()
{
    auto a = f();
    std::cout << *a[0] << " " << *a[1] << "\n";

    for (auto const & p : f())
        std::cout << *p << "\n";
}

请注意,支持elision(特别是在直接列表初始化的上下文中)和仅可移动类型的聚合初始化是C ++ 11的新功能,供应商支持只是缓慢发展,因此bug并不少见。

还要注意std::vector<std::unique_ptr<int>>的列表初始化(直接或复制)是行不通的,因为那个需要一个std::initializer_list的构造函数调用,它不能处理仅可移动的类型。相比之下,std::array有效,因为列表初始化在这种情况下是聚合初始化。