使用本机数组,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);
}
全部失败。这里有很多问题。如何修复它们?非常感谢。
答案 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
有效,因为列表初始化在这种情况下是聚合初始化。