Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do STL containers copy objects?

I know STL containers like vector copies the object when it is added. push_back method looks like:

void push_back ( const T& x );

I am surprised to see that it takes the item as reference. I wrote a sample program to see how it works.

struct Foo
{
    Foo()
    {
        std::cout << "Inside Foo constructor" << std::endl;
    }

    Foo(const Foo& f)
    {
        std::cout << "inside copy constructor" << std::endl;
    }
};

Foo f;
std::vector<Foo> foos;
foos.push_back(f);

This copies the object and I can see it is calling copy-constructor.

My question is, when the push_back takes item as reference, how it is calling copy-constructor? Or am I missing something here?

Any thoughts..?

like image 501
Navaneeth K N Avatar asked Nov 07 '09 13:11

Navaneeth K N


People also ask

How are C++ STL containers implemented?

They are implemented as class templates, which allows great flexibility in the types supported as elements. The container manages the storage space for its elements and provides member functions to access them, either directly or through iterators (reference objects with similar properties to pointers).

What is used to implement STL containers to hold different data types?

In STL, we have various types of container classes like Array, vector, queue, deque, list, map, set, etc. These containers are generic in nature and are implemented as class templates. Containers are dynamic in nature and can be used to hold various types of objects.


2 Answers

It probably uses "placement new" to construct the object in-place in its internal array. Placement new doesn't allocate any memory; it just places the object where you specify, and calls the constructor. The syntax is new (address) Class(constructor_arguments).

The copy constructor T::T(T const &) is called to create the copy in-place. Something like this (simplified):

template<T>
void vector<T>::push_back(T const &item) {
    // resize if necessary
    new (&d_array[d_size++]) T(item);
}

Note that T must have a copy constructor for this to work. By default (if you do nothing), it gets one for free. If you define it explicitly, it must be public for vector<T> to work.

Here's how GNU's libstdc++ does it, but I doubt that it'll be very enlightening. There is an allocator (the second template argument to vector) that makes it less straightforward.

like image 107
Thomas Avatar answered Oct 11 '22 13:10

Thomas


The C++ SDK always takes const T & as function parameter for efficiency.

In your case if it take T as parameter, the copy action will be done twice, one for passing it to function push_back(f), one for internal adding it to the container. And by taking const T& as parameter only one copy is needed!

like image 31
learner Avatar answered Oct 11 '22 13:10

learner