Skip to content

Inserting object to C++11 vector without copy constructor

November 10, 2011

What really happens when you insert object to a vector? Well, lets find out!

Lets consider code like this, first we have a class Foo:

class Foo
{
   //Foo stuff.
};

Now it is time to use it, for example like this:

std::vector<Foo> fooVector;
//Some code here...
for(int i = 0; i < 10; ++i)
{
  Foo bar;
  //Do something with bar here.
  fooVector.push_back(bar);
}

What will happen here, is that a copy constructor for Foo will be called, and depending on your Foo implementation, it can be very time consuming.

Ok so, maybe this would help:

std::vector<Foo> fooVector;
//Some code here...
for(int i = 0; i < 10; ++i)
{
  fooVector.push_back(Foo());
  //Do something with last fooVector element.
}

Looks like it might be better! However this solution will still call the copy constructor. In this scenario, fallowing will happen:

  • Constructor for Foo will be called and TEMP variable will be created.
  • Copy constructor will be called, returned value will be inserted to vector.
  • Destructor for TEMP object will be called.

And this cannot be optimized by the compiler. While it might be faster than the previous solution, it can still be very time consuming.

So what to do? Unfortunatelly, in C++03 in search for fastest implementation, our only option is to use pointers here. Whether it would be smart pointer or raw pointer, you will not get away without them.

For example we could just do this:

std::vector<Foo*> fooVector;
//Some code here...
for(int i = 0; i < 10; ++i)
{
  fooVector.push_back(new Foo());
  //Do something with last fooVector element.
}
//Don't forget to take care of your memory or use smart pointers!

While this is fine in optimization way, it does not keep the C++ style, as if the fooVector is local variable with life time limited by its scope, that is — it should be created in stack and it does not make much sense to keep its elements in the heap if we will need them only for the same scope as our vector. However in C++11 we will be able to get around in this situation in more of the C++ style! With emplace (or emplace_back), that does the fallowing:

The element is constructed in-place, i.e. no copy or move operations are performed. The constructor of the element is called with exactly the same arguments, as supplied to the function.

We will be able to keep the C++ style in this kind of situations while maintaining high C++ performance.
In the “old” C++ I’d suggest to use ptr_container provided by boost for this situation instead of raw pointer use. Comparison can be found on my post about RAII.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: