用 unique_pointers 填充向量

Posted

技术标签:

【中文标题】用 unique_pointers 填充向量【英文标题】:Filling of vector with unique_pointers 【发布时间】:2020-06-16 11:50:43 【问题描述】:

我必须上课 ABB 派生自 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 类中缺少适当的构造函数有关? 2.当我制作push_back时,我应该总是使用std:moveunique_pointer吗?我问是因为我怀疑如果没有std::move,是否会隐式创建一些副本。另一方面,也许编译器做了一些优化并且可以识别这种“短”结构?

【问题讨论】:

【参考方案1】:
    此错误是否与向量中缺少适当的构造函数有关

这是一种解释。

(交互者?)

没有。

还是在 A/B 类?

没有。

问题是您使用的向量构造函数接受std::initializer_list。该类复制参数。唯一指针是不可复制的,所以这不起作用。

    当我制作 push_back 时,我是否应该始终使用 unique_pointer 执行 std:move?

给定一个左值表达式,如果你想将它移动到向量中,那么你必须使用std:move。您不需要也不应该将std:move 与已经是右值的表达式一起使用。

【讨论】:

【参考方案2】:
    此错误是否与 vector (interator?) 或 A/B 类中缺少适当的构造函数有关?

也不是,这是因为std::unique_ptr的复制构造函数被隐式删除(由于用户声明的移动构造函数);你不能复制std::unique_ptr,你移动它。

    当我创建push_back 时,我是否应该始终使用std:moveunique_pointer?我问是因为我怀疑如果没有std::move,是否会隐式创建一些副本。另一方面,也许编译器做了一些优化并且可以识别这种“短”结构?

是的,当在带有左值参数的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;

【讨论】:

以上是关于用 unique_pointers 填充向量的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 5099: [POI2018]Pionek

p3412 [POI2005]SKO-Knights

java poi 生成word表格怎么 让表格填充整个页面和合并单元格

[武汉加油] bzoj 5099: [POI2018]Pionek 几何+双指针

用随机字节填充字节向量

用子类填充的基类向量不起作用