nnrales
nnrales

Reputation: 1519

When are the variables allocated and initialized?

Please take a look at this code:

template <typename T>
class matrix
{
    private:
        std::vector<T> vec_;

public:
    matrix(size_t rows , size_t cols) : rows_(rows) , cols_(cols) , vec_(rows_ * cols_)
    {
    }       
    size_t rows_;
    size_t cols_;   

};

This is a way to declare a class. I am just wondering where the std::vector is being allocated and where it is being initialized?

What happens when I declare a variable? Is the space for it allocated in the stack before the constructor is called or is allocated and initialized in the constructor?

What is the difference between declaring a vector with size 10

 std::vector<T> vec_(10);

and calling the constructor of vec_ with the size 10 in the constructor?

 matrix() : vec_(10)

I wanted to understand how objects are allocated and initialized in C++.

Also I can create a constructor without calling the constructor of std::vector

 matrix() {}

What is happening here? Since I am not calling the constructor for the vector does the compiler call it own its own? Can the vector object utilized? Or is it called automatically because I declared std::vector to be a variable in my class?

Also does initializing as std::vector vec(10), have the same effect as calling resize/reserve. Which is it closer to?

Upvotes: 1

Views: 56

Answers (2)

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140168

that code:

private:
    std::vector<T> vec_(10);

doesn't compile as Bo noted. But you could do this in a legal & performant way in c++11 (as performant because of copy elision: assignment operator is very likely to be turned into a copy constructor because object is being initialized at this very line):

private:
    std::vector<T> vec = std::vector<T>(10);

So, that previous construct and this one:

public: 
     matrix() : vec_(10)

do the same: vec_ will be built once, with 10 elements inside it, exactly like resize would do, except that it's faster because you don't have to create an empty vector and resize it.

For the second part of your question: If you create your instance using a default constructor, the compiler will call the default constructor for all class members, so it is perfectly safe.

Beware: POD objects are not zeroed, which may be a problem, so it's better to set pointers to nullptr, integers to 0, etc... or you get uninitialized values, not good when entering the destructor with an invalid pointer passed to delete ...

Of course, it will fail to compile if one of the members has only non-default constructors (needing a parameter).

Upvotes: 2

Bo Persson
Bo Persson

Reputation: 92261

The members of a class object are initialized in the order they are declared. In this case it is this order:

private:
    std::vector<T> vec_;

public:
   size_t rows_;
   size_t cols_;   

so when executing the initializer list

matrix(size_t rows , size_t cols) : rows_(rows) , cols_(cols) , vec_(rows_ * cols_)

the real order is

vec_(rows_ * cols_), rows_(rows) , cols_(cols) 

which is using rows_ and cols_ before they are initialized. And bad things will happen.

Upvotes: 2

Related Questions