Reputation: 1519
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
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
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