【问题标题】:How to return an array / vector of unique pointers? [duplicate]如何返回唯一指针的数组/向量? [复制]
【发布时间】:2014-08-19 10:42:35
【问题描述】:

使用原生数组、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);
}

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

【问题讨论】:

  • 您能否列出您遇到的问题,并针对每个问题简要说明您尝试解决的问题?
  • 我在代码中显示了问题
  • 错误与返回数组无关。大约是initializer_list
  • 不要在返回语句中使用 std::move(a)。在所有情况下, a 已经是一个临时对象。
  • @Krozark:它肯定不是临时对象,因为它显然有一个名字。

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


【解决方案1】:

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

#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";
}

但请注意,大括号省略(尤其是在直接列表初始化的上下文中)和仅可移动类型的聚合初始化是 C++11 的新特性,供应商对此的支持进展缓慢,因此错误并不少见。

还请注意,std::vector&lt;std::unique_ptr&lt;int&gt;&gt; 的列表初始化(直接或复制)无法正常工作,因为这需要一个构造函数调用,该调用采用 std::initializer_list,它无法处理仅可移动的类型。相比之下,std::array 有效,因为在这种情况下,列表初始化是聚合初始化。

【讨论】:

  • 为什么要使用两个大括号 {{ }}?
  • @user1899020:已添加。它被称为“大括号省略”,没有人理解它(甚至可能是你的编译器),所以我选择将所有大括号保留在它们所属的位置。一个好的编译器(Clang)会告诉你如果你忘记了你需要做什么。
  • 我总是对初始化感到困惑。外支架和内支架是干什么用的?谢谢。
  • @user1899020:我不是在开玩笑。没有人理解大括号省略。每个本身就是聚合的对象都有一对大括号。
猜你喜欢
  • 2014-09-12
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多