Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call constructor of objects contained in a std::vector?

When I create a std::vector of objects, the constructor of these objects is not always called.

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

struct C {
    int id;
    static int n;
    C() { id = n++; }   // not called
//  C() { id = 3; }     // ok, called
};

int C::n = 0;


int main()
{
    vector<C> vc;

    vc.resize(10);

    cout << "C::n = " << C::n << endl;

    for(int i = 0; i < vc.size(); ++i)
        cout << i << ": " << vc[i].id << endl;  
}

This is the output I get:

C::n = 1
0: 0
1: 0
2: 0
...

This is what I would like:

C::n = 10
0: 0
1: 1
2: 2
...

In this example, am I forced to resize the vector and then initialise its elements "manually"?
Could the reason be that the elements of a vector are not initialised in an ordered way, from the first to the last, and so I cannot obtain a deterministic behaviour?

What I would like to do, is to easily count the number of objects created in a program, in different containers, in different points of the code, and to give a single id to each of them.

Thank's!

like image 237
Pietro Avatar asked Jul 17 '10 16:07

Pietro


People also ask

Does vector copy constructor?

Yes, old objects are destroyed after they are copied to the new buffer.

Which constructor is called when object is created?

Constructor in C++ is a special method that is invoked automatically at the time of object creation. It is used to initialize the data members of new objects generally. The constructor in C++ has the same name as the class or structure.

How do you initialize a vector constructor?

You can initialize a vector by using an array that has been already defined. You need to pass the elements of the array to the iterator constructor of the vector class. The array of size n is passed to the iterator constructor of the vector class.

Can constructor be called directly?

No, you cannot call a constructor from a method. The only place from which you can invoke constructors using “this()” or, “super()” is the first line of another constructor. If you try to invoke constructors explicitly elsewhere, a compile time error will be generated.


1 Answers

the constructor of these objects is not always called.

Yes, it is, but it's not the constructor you think. The member function resize() is actually declared like this:

void resize(size_type sz, T c = T());

The second parameter is the object to copy into each of the newly inserted elements of the vector. If you omit the second parameter, it default constructs an object of type T then copies that object into each of the new elements.

In your code, a temporary C is constructed and the default constructor is called; id is set to 0. The implicitly declared copy constructor is then called ten times (to insert ten elements into the vector), and all of the elements in the vector have the same id.

[Note for those who are interested: in C++03, the second parameter of resize() (c) is taken by value; in C++0x it is taken by const lvalue reference (see LWG Defect 679)].

In this example, am I forced to resize the vector and then initialise its elements "manually"?

You can (and probably should) insert the elements into the vector individually, e.g.,

std::vector<C> vc;
for (unsigned i(0); i < 10; ++i)
    vc.push_back(C());
like image 96
James McNellis Avatar answered Oct 25 '22 09:10

James McNellis