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.
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.
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.
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.
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.
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With