简体   繁体   中英

Filling of vector with unique_pointers

I have to classes A and B .
B derives from A .
I have also vector std::vector<std::unique_ptr<A>> samples

This piece of code works:

std::vector<std::unique_ptr<A>> samples;
samples.push_back(std::make_unique<B>(param_1, param_2));

But this one doesn't:

std::vector<std::unique_ptr<A>> samples = {std::make_unique<B>(param_1, param_2)};

and generates such error:

/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

Questions
1. Is this error connected with lack of proper constructor in vector ( interator ?) or in A/B class?
2. 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?

  1. Is this error connected with lack of proper constructor in vector

That's one interpretation.

(interator?)

No.

or in A/B class?

No.

The issue is that the vector constructor that you use, accepts a std::initializer_list . That class copies the arguments. Unique pointers are not copiable, so this does not work.

  1. When I make push_back, should I do always std:move with unique_pointer or not?

Given an lvalue expression, if you want to move that into the vector, then you must use std:move . You don't need to, and shouldn't use std:move with expressions that are already rvalues.

  1. Is this error connected with lack of proper constructor in vector ( interator ?) or in A/B class?

Neither, this is due to the fact that the copy constructor of std::unique_ptr is implicitly deleted (due to the user-declared move constructor); you cannot copy a std::unique_ptr , you move it.

  1. 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?

Yes, when invoking push_back on a vector of std::unique_ptr elements with an lvalue argument, you need to use std::move to invoke the move constructor of std::unique_ptr (and not its implicitly deleted copy constructor).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM