Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moving unique_ptr in the declaration of a vector [duplicate]

I try to move some unique_ptr in a vector during it declaration and I get a error. I think that I make a copy without knowing it.

I don't understand why I get the problem at the declaration while it works very well during a push_back.

I simplified the problem in few lines.

#include <iostream>
#include <vector>
#include <memory>
using namespace std;

int main() {

    unique_ptr<int> i1 = make_unique<int>(142);
    unique_ptr<int> i2 = make_unique<int>(242);
    unique_ptr<int> i3 = make_unique<int>(342);


    vector<unique_ptr<int>> v;

    //Those lines work
    v.push_back(move(i1));
    v.push_back(move(i2));
    v.push_back(move(i3));

    //ERROR
    vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)}; 

    return 0;
}

The error is :

use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const
std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp =
std::default_delete<int>]'
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

What am I missing ?

Thanks !

like image 746
Nix Avatar asked Jan 12 '17 15:01

Nix


People also ask

Can you move a unique_ptr?

A unique_ptr can only be moved. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it. We recommend that you restrict an object to one owner, because multiple ownership adds complexity to the program logic.

Is unique_ptr null after move?

Yes, you can compare it to nullptr after the move and it is guaranteed to compare equal. This is clearly true after calling release(). But std::move doesn't call release(). So how does the compiler know to restore the invariant of the unique_ptr?

What happens when unique_ptr goes out of scope?

An​ unique_ptr has exclusive ownership of the object it points to and ​will destroy the object when the pointer goes out of scope. A unique_ptr explicitly prevents copying of its contained pointer. Instead, the std::move function has to be used to transfer ownership of the contained pointer to another unique_ptr .

When should we use unique_ptr?

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.


1 Answers

When you do

vector<unique_ptr<int>> v2 {move(i1), move(i2), move(i3)};

you are not actually moving directly into the vector v2. Instead the compiler will create a std::initializer_list of the moved unique pointers, and pass that list object to the std::vector constructor which will then attempt to copy the elements from the initializer list.

Unfortunately I know of no way to solve the problem, of using the intermediate initializer list to initialize a vector of unique pointers.

like image 100
Some programmer dude Avatar answered Oct 18 '22 16:10

Some programmer dude