How are objects initialized when they are used to initialize a STL container?

1
2
3
4
5
6
class t {
public:
    int i;
    t() { i = 44; cout << "Ordinary\n"; }
    t(const t& x) { cout << x.i << " Copy\n"; }
};


Given that class, if write this:
vector<t> v1(3);

then the output is:
Ordinary
44 copy
44 copy
44 copy


In this case, why the constructor is called 4 times when I only create 3 objects of type t? What is passed to the copy constructor as argument?

And if I avoid the copy constructor:
1
2
3
4
5
class t {
public:
    int i;
    t() { i = 44; cout << "Ordinary\n"; }
};


the output then becomes:
ordinary


Now, why is there only one call to the constructor instead of 3, or 4 if I take the previous output into consideration?!

How this actually works? Anybody please explain...
Last edited on
And if I avoid the copy constructor:
YOu cannot avoid copy constructor. If you did not provide one yourself, compiler will generate one. There still one created object and 3 copies.

Well, I can say for sure that you are using C++98 standard and not C++11, as that is the behavior you get in it.

Look at the vector constructor signature: http://en.cppreference.com/w/cpp/container/vector/vector
explicit vector( size_type count, const T& value = T(), const Allocator& alloc = Allocator()); 

So if you do not provide a value, to fill, it will create one using default constructor. And the descrption of that costructor says that vector is populated with copies of passed element. So: one default created original and three copies to populate vector.



In C++11 behavior of that constructor changed: if you do not provide a value, it will create them in place using default constructor. No copies ar made.

Turn on C++11 (or C++14) mode and see for yourself.
From: http://www.cplusplus.com/reference/vector/vector/
1
2
explicit vector (size_type n, const value_type& val = value_type(),
                 const allocator_type& alloc = allocator_type());

Note the underlined default argument. value_type() calls your default constructor. This is what puts out "Ordinary".

From: http://www.cplusplus.com/reference/vector/vector/vector/
(2) fill constructor
Constructs a container with n elements. Each element is a copy of val.

Since you are using vector's fill constructor, you are making 3 copies of val. This causes "44 copy" to be emitted three times.

In the second snippet when you omit the copy constructor, the compiler provides an implicit copy constructor (without the cout). So in the second snippet, you are still calling a copy constructor 3 times in addition to the call to the default construcotr.
Based on what you've said, I tried this program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <vector>
using namespace std;

class t {
public:
    int i;
    t()
    {
        i = 44;
        cout << "Ordinary\n";
    }

    t(int val)
    {
        i = val;
        cout << "Extra-ordinary\n";
    }

    t(const t& x)
    {
        i = x.i + 1;
        cout << x.i << " Copy\n";
    }
};

int main()
{
    vector<t> v1(3, t(4));

    cout  << endl;

    for(int j = 0; j < v1.size(); j++) cout << v1[j].i << endl;

    return 0;
}


The output of this program:
Extra-ordinary
4 Copy
4 Copy
4 Copy

5
5
5


Where did the object with value 4 to i go? Is this memory leak?

However, after this observation and what you've explained, can I say-
For fill constructor of vector, a temporary object is created using the object-constructor provided (default constructor if none available). And this temporary object is then sent to the copy constructor of that object n times as argument and the resultant n objects are contained in the vector. But the temporary object is discarded.

Are my assumptions correct and are those true for all STL containers, rather than just vector?

Kindly explain...
Last edited on
Where did the object with value 4 to i go?
It is destroyed when it is not needed anymore. Make destructor output something too and see for yourself.

Is this memory leak?
No. It is almost impossible to leak automatic memory.

Are my assumptions correct and are those true for all STL containers, rather than just vector?
Yes. No. Maybe.
Not all containers have fill constructor. Also it behaves that way in outdated 1998 C++ Standard. In modern 2011 standard behavior have changed and it does not create object when it is not provided a value.
Thanks a lot...
Topic archived. No new replies allowed.