Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

emplace_back() does not behave as expected

Tags:

I wrote a simple program to play around with in-place creation of objects inside standard library containers. This is what I wrote:

#include <vector> #include <iostream>  class AB { public:    explicit AB(int n);    AB(const AB& other) = delete;    AB(AB&& other);    AB& operator=(const AB& other) = delete;    AB& operator=(AB&& other) = default; private:    int i; };  AB::AB(int n): i( n ) {    std::cout << "Object created." << std::endl; };  AB::AB(AB&& other): i( std::move(other.i) ) {    std::cout << "Object moved." << std::endl; };  int main() {    std::vector< AB > v;    v.emplace_back(1);    v.emplace_back(2);    v.emplace_back(3); }; 

I compiled it with g++ (version 4.8.2). After running the output, I got:

Object created. Object created. Object moved. Object created. Object moved. Object moved. 

But I expected something like this:

Object created. Object created. Object created. 

I thought the whole point of emplacement was to get rid of the movement constructor calls. Are there any requirements in class AB that are not met?

Thanks for your help.

like image 556
WielandK Avatar asked May 30 '14 06:05

WielandK


People also ask

Which is better Push_back or Emplace_back?

The difference in the efficiency of push_back and emplace_back depends on the type of our vector. If the vector is a built-in type, there is no difference between the efficiency of push_back and emplace_back. If the vector type is class or struct, emplace_back is more efficient than push_back.

What is the function of Emplace_back?

The C++ function std::vector::emplace_back() inserts new element at the end of vector. Reallocation happens if there is need of more space. This method increases container size by one.

Why is Emplace_back faster than Push_back?

because emplace_back would construct the object immediately in the vector, while push_back , would first construct an anonymous object and then would copy it to the vector.

Does Emplace_back use move constructor?

Calling emplace_back will call the move constructor of std::string when std::move is used, which could save on a copy (so long as that string isn't stored in a SSO buffer). Note that this is essentially the same as push_back in this case.


1 Answers

The problem is that your vector is being resized as you add more elements, resulting in extra moves. If you reserve enough capacity at the start, you get the expected result:

   std::vector< AB > v;    v.reserve(3);    v.emplace_back(1);    v.emplace_back(2);    v.emplace_back(3); 

gives

Object created. Object created. Object created. 

On gcc 4.8.2. Note that you can track the vector's growth in your original code by looking at v.capacity().

like image 70
juanchopanza Avatar answered Oct 12 '22 23:10

juanchopanza