Sunday, 13 July 2014

Using std::set emplace

Emplace is a C++11 feature intended to minimize unnecessary copy or move operations for STL container elements.

Prior to emplace, adding an element to a set is done using insert. With it comes the cost of a copy operation, as the following output shows:

#include <iostream>
#include <set>
using namespace std;

class a
{
public:
    a(int i)
    {
        cout << "constructor" << i << endl;
    }
    ~a()
    {
        cout << "destructor" << endl;
    }
    a(const a& other)
    {
        cout << "copy constructor" << endl;
    }
    friend bool operator<(const a& me, const a& other)
    {
        cout << "comparison" << endl;
        return true;
    }
   
};

int main()
{
    set<a> aset;
    cout << "inserting" << endl;
    aset.insert(a(1));
    cout << "done inserting" << endl;
    return 0;
}


Output:

inserting
constructor1
copy constructor
destructor
done inserting
destructor


When the emplace operator is used, the element can be constructed "in place", as the parameters to the constructors are forwarded using variadic templates. Only the constructor and destructor is called here:

int main()
{
    set<a> aset;
    cout << "emplacing" << endl;
    aset.emplace(1);
    cout << "done emplacing" << endl;
}


Output:

emplacing
constructor1
done emplacing
destructor


Remember that emplace takes the constructor arguments directly, so it is a mistake to do this:

aset.emplace(a(1));

because that would first construct the element on the stack, then call the copy constructor to place it in the container.

No comments:

Post a Comment