用 unique_pointers 填充矢量
Filling of vector with unique_pointers
我必须 classes A
和 B
.
B
派生自 A
.
我还有矢量 std::vector<std::unique_ptr<A>> samples
这段代码有效:
std::vector<std::unique_ptr<A>> samples;
samples.push_back(std::make_unique<B>(param_1, param_2));
但是这个没有:
std::vector<std::unique_ptr<A>> samples = {std::make_unique<B>(param_1, param_2)};
并产生这样的错误:
/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<A>*; _ForwardIterator = std::unique_ptr<A>*]’:
/usr/include/c++/9/bits/stl_uninitialized.h:307:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const std::unique_ptr<A>*; _ForwardIterator = std::unique_ptr<A>*; _Tp = std::unique_ptr<A>]’
/usr/include/c++/9/bits/stl_vector.h:1582:33: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::unique_ptr<A>*; _Tp = std::unique_ptr<A>; _Alloc = std::allocator<std::unique_ptr<A> >]’
/usr/include/c++/9/bits/stl_vector.h:626:2: required from ‘std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::unique_ptr<A>; _Alloc = std::allocator<std::unique_ptr<A> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::unique_ptr<A> >]’
my_file.cpp:88:113: required from here
/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
127 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
| ^~~~~
make: *** [makefile:15: cpp] Error 1
问题
1. 此错误是否与 vector
(interator
?) 或 A/B
class?
中缺少适当的构造函数有关
2. 当我制作push_back
时,我是否应该总是std:move
和unique_pointer
?我问是因为我怀疑如果没有 std::move
是否会隐式创建一些副本。另一方面,也许编译器做了一些优化,可以识别这样的 "short" 结构?
- Is this error connected with lack of proper constructor in vector
这是一种解释。
(interator?)
没有
or in A/B class?
没有
问题是您使用的向量构造函数接受 std::initializer_list
。 class 复制参数。唯一指针不可复制,所以这不起作用。
- When I make push_back, should I do always std:move with unique_pointer or not?
给定一个左值表达式,如果你想把它移到向量中,那么你必须使用 std:move
。您不需要也不应该将 std:move
与已经是右值的表达式一起使用。
- Is this error connected with lack of proper constructor in
vector
(interator
?) or in A/B
class?
也不是,这是因为std::unique_ptr
的复制构造函数被隐式删除了(由于用户声明的移动构造函数);您无法复制 std::unique_ptr
,您可以 移动 它。
- When I make
push_back
, should I do always std:move
with unique_pointer
or not? I ask because I have doubts if maybe without std::move
there are created implicitly some copies. In other hand maybe compiler does some optimalizations and can recognize such "short" construction?
是的,当在带有左值参数的 std::unique_ptr
元素的向量上调用 push_back
时,您需要使用 std::move
来调用 std::unique_ptr
的移动构造函数(而不是它隐式删除的复制构造函数)。
#include <memory>
#include <vector>
int main() {
std::vector<std::unique_ptr<int>> v;
auto value = std::make_unique<int>(1);
// v.push_back(value); // error (attempts to copy)
v.push_back(std::move(value)); // lvalue "std::to_xvalue" -> move ctor
v.push_back(std::make_unique<int>(2)); // already an rvalue -> move ctor
return 0;
}
我必须 classes A
和 B
.
B
派生自 A
.
我还有矢量 std::vector<std::unique_ptr<A>> samples
这段代码有效:
std::vector<std::unique_ptr<A>> samples;
samples.push_back(std::make_unique<B>(param_1, param_2));
但是这个没有:
std::vector<std::unique_ptr<A>> samples = {std::make_unique<B>(param_1, param_2)};
并产生这样的错误:
/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const std::unique_ptr<A>*; _ForwardIterator = std::unique_ptr<A>*]’:
/usr/include/c++/9/bits/stl_uninitialized.h:307:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = const std::unique_ptr<A>*; _ForwardIterator = std::unique_ptr<A>*; _Tp = std::unique_ptr<A>]’
/usr/include/c++/9/bits/stl_vector.h:1582:33: required from ‘void std::vector<_Tp, _Alloc>::_M_range_initialize(_ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _ForwardIterator = const std::unique_ptr<A>*; _Tp = std::unique_ptr<A>; _Alloc = std::allocator<std::unique_ptr<A> >]’
/usr/include/c++/9/bits/stl_vector.h:626:2: required from ‘std::vector<_Tp, _Alloc>::vector(std::initializer_list<_Tp>, const allocator_type&) [with _Tp = std::unique_ptr<A>; _Alloc = std::allocator<std::unique_ptr<A> >; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<std::unique_ptr<A> >]’
my_file.cpp:88:113: required from here
/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
127 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
| ^~~~~
make: *** [makefile:15: cpp] Error 1
问题
1. 此错误是否与 vector
(interator
?) 或 A/B
class?
中缺少适当的构造函数有关
2. 当我制作push_back
时,我是否应该总是std:move
和unique_pointer
?我问是因为我怀疑如果没有 std::move
是否会隐式创建一些副本。另一方面,也许编译器做了一些优化,可以识别这样的 "short" 结构?
- Is this error connected with lack of proper constructor in vector
这是一种解释。
(interator?)
没有
or in A/B class?
没有
问题是您使用的向量构造函数接受 std::initializer_list
。 class 复制参数。唯一指针不可复制,所以这不起作用。
- When I make push_back, should I do always std:move with unique_pointer or not?
给定一个左值表达式,如果你想把它移到向量中,那么你必须使用 std:move
。您不需要也不应该将 std:move
与已经是右值的表达式一起使用。
- Is this error connected with lack of proper constructor in
vector
(interator
?) or inA/B
class?
也不是,这是因为std::unique_ptr
的复制构造函数被隐式删除了(由于用户声明的移动构造函数);您无法复制 std::unique_ptr
,您可以 移动 它。
- When I make
push_back
, should I do alwaysstd:move
withunique_pointer
or not? I ask because I have doubts if maybe withoutstd::move
there are created implicitly some copies. In other hand maybe compiler does some optimalizations and can recognize such "short" construction?
是的,当在带有左值参数的 std::unique_ptr
元素的向量上调用 push_back
时,您需要使用 std::move
来调用 std::unique_ptr
的移动构造函数(而不是它隐式删除的复制构造函数)。
#include <memory>
#include <vector>
int main() {
std::vector<std::unique_ptr<int>> v;
auto value = std::make_unique<int>(1);
// v.push_back(value); // error (attempts to copy)
v.push_back(std::move(value)); // lvalue "std::to_xvalue" -> move ctor
v.push_back(std::make_unique<int>(2)); // already an rvalue -> move ctor
return 0;
}