为什么我不能用 {std::move(first), std::move(second)} 实例化 std::vector<std::unique_ptr<int>>?
Why can I not instantiate std::vector<std::unique_ptr<int>> with {std::move(first), std::move(second)}?
我有一个简单的函数,它应该构造一些对象和 return 它们的向量,同时还转移所有权。我认为最好的方法就是简单地 returning a std::vector<std::unique_ptr<int>>
个对象(假设它们是 int
)。
当我尝试以下功能时:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
return {std::move(first), std::move(second)};
}
我收到了一个非常非常长的编译错误,结尾为:
xmemory0(737): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)':
attempting to reference a deleted function
我认为问题出在函数本身,但以下解决方案工作正常:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
std::vector<std::unique_ptr<int>> results;
results.push_back(std::move(first));
results.push_back(std::move(second));
return results;
}
为什么第二种解决方案有效而第一种无效?有没有一种解决方法可以让我在初始化列表中使用简短的语法?
Why does the second solution work but not the first one?
您使用的列表初始化语法调用接受 std::initializer_list
的构造函数。 std::initializer_list
不可移动,并且 std::initializer_list<std::unique_ptr<T>>
不可复制,因此无法调用构造函数。
在后面的例子中你使用了默认的构造函数,所以没有问题。
Is there a workaround that would allow me to use the short and simple syntax with the initializer list?
您可以列出初始化一个数组,并使用一对移动迭代器:
std::array arr{
std::make_unique<int>(1),
std::make_unique<int>(2),
};
return std::vector(
std::make_move_iterator(std::begin(arr)),
std::make_move_iterator(std::end(arr))
);
有一个 proposal 可以使 std::initializer_list
可移动,但没有被采纳(还没有被采纳;谁知道未来会怎样)。
在我的平台上,相关代码是:
vector(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type())
: _Base(__a)
{ _M_range_initialize(__l.begin(), __l.end(),
random_access_iterator_tag());
}
而 _M_range_initialize()
只是从迭代器 复制 ,而不是移动自。
我有一个简单的函数,它应该构造一些对象和 return 它们的向量,同时还转移所有权。我认为最好的方法就是简单地 returning a std::vector<std::unique_ptr<int>>
个对象(假设它们是 int
)。
当我尝试以下功能时:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
return {std::move(first), std::move(second)};
}
我收到了一个非常非常长的编译错误,结尾为:
xmemory0(737): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)':
attempting to reference a deleted function
我认为问题出在函数本身,但以下解决方案工作正常:
std::vector<std::unique_ptr<int>> create_stuff() {
auto first = std::make_unique<int>(1);
auto second = std::make_unique<int>(2);
std::vector<std::unique_ptr<int>> results;
results.push_back(std::move(first));
results.push_back(std::move(second));
return results;
}
为什么第二种解决方案有效而第一种无效?有没有一种解决方法可以让我在初始化列表中使用简短的语法?
Why does the second solution work but not the first one?
您使用的列表初始化语法调用接受 std::initializer_list
的构造函数。 std::initializer_list
不可移动,并且 std::initializer_list<std::unique_ptr<T>>
不可复制,因此无法调用构造函数。
在后面的例子中你使用了默认的构造函数,所以没有问题。
Is there a workaround that would allow me to use the short and simple syntax with the initializer list?
您可以列出初始化一个数组,并使用一对移动迭代器:
std::array arr{
std::make_unique<int>(1),
std::make_unique<int>(2),
};
return std::vector(
std::make_move_iterator(std::begin(arr)),
std::make_move_iterator(std::end(arr))
);
有一个 proposal 可以使 std::initializer_list
可移动,但没有被采纳(还没有被采纳;谁知道未来会怎样)。
在我的平台上,相关代码是:
vector(initializer_list<value_type> __l, const allocator_type& __a = allocator_type()) : _Base(__a) { _M_range_initialize(__l.begin(), __l.end(), random_access_iterator_tag()); }
而 _M_range_initialize()
只是从迭代器 复制 ,而不是移动自。