Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why does vector.emplace_back call the move-constructor?

Tags:

c++

vector

struct Object {  
    Object() { cout << "constructor\n"; }
    Object(const Object &) { cout << "copy constructor\n"; }
    Object(Object &&) { cout << "move constructor\n"; }
};

int main() {
    vector<Object> v;
    v.reserve(10);
    v.emplace_back(Object{});
}

This gives me the following output:

constructor
move constructor

Why? I thought that emplace_back does create the Object in place, so that no copy or move constructors have to be called.
From the description:

The element is constructed in-place, i.e. no copy or move operations are performed.

EDIT: Ah, okay, it seems that I fundamentally misunderstood emplace_back(). You don't have to have the Object as an argument, since it is automatically created in place for you. You only have to give the arguments for the Object-constructor to emplace_back().

So, if I had a new constructor like this:

Object(int) { cout << "int constructor\n"; }   

I would call emplace_back like this:

v.emplace_back(42);  

instead of this:

v.emplace_back(Object(42));

Makes sense now, thanks a lot!

EDIT2: I wish I could accept all of your answers! :-P

like image 869
gartenriese Avatar asked Feb 18 '14 15:02

gartenriese


People also ask

Does Emplace_back call constructor?

This code demonstrates that emplace_back calls the copy constructor of A for some reason to copy the first element. But if you leave copy constructor as deleted, it will use move constructor instead.

Does vector have a move constructor?

No. It doesn't call the move constructor. To call move constructor of element you will have to call std::move while pushing to vector itself.

What is the use of move constructor?

A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying.

What does vector Emplace_back do?

vector::emplace_back() This function is used to insert a new element into the vector container, the new element is added to the end of the vector.


4 Answers

emplace_back forwards its arguments to the constructor of the vector element class, called in-place on the next available position of the vector.

v.emplace_back(Object{});

is sort of equivalent to:

{
     Object tmp;
     v.emplace_back(std::move(tmp));
}

That's why you are getting a regular constructor call followed by a move constructor call. If you want to append a new object with emplace_back, just call:

v.emplace_back();

Just for the sake of completeness, another reason why emplace_back might call a move constructor is: emplace_back may cause the vector to grow, and thus move its initial contents to their new memory location. This is not the problem here, because calling reserve guarantees enough capacity, but generally it's an answer to the question.

like image 97
Martin J. Avatar answered Oct 15 '22 05:10

Martin J.


v.emplace_back(Object{}); will call a placement new new (place) Object(Object{}) so a move constructor.

Use v.emplace_back(); to avoid to call extra object constructor,
which will result in new (place) Object;

like image 37
Jarod42 Avatar answered Oct 15 '22 05:10

Jarod42


emplace_back calls whatever constructor matches the arguments you pass it. In this case you have chosen to pass Object{}, which matches the Object&& move constructor.

When the description says, "no move or copy is performed", it means apart from the object construction that you specify. If that construction happens to be a move or copy then of course it is performed.

If you want emplace_back to use the no-args constructor then pass it no arguments: v.emplace_back().

like image 21
Steve Jessop Avatar answered Oct 15 '22 05:10

Steve Jessop


The version you are linking is for passing constructor arguments. To achieve the desired effect, you could call v.emplace_back();

like image 34
François Moisan Avatar answered Oct 15 '22 04:10

François Moisan