dynamic allocation and values of data members

S

subramanian100in

Consider the following classes without ctors.

class Sample
{
private:
double d_val;
double* d_ptr;
};

class Test
{
private:
int i_val;
int* i_ptr;
Sample obj;
};

Suppose I allocate
Test* t = new Test();

Since I have mentioned 'new Test()' instead of just 'new Test',
will this statement set
t->i_val to zero, t->i_ptr to null pointer, t->obj.d_val to 0.0,
t->obj.d_ptr to null pointer ?

What does the standard say in this regard ?

Kindly explain.

Thanks
V.Subramanian
 
P

Pascal J. Bourguignon

Consider the following classes without ctors.

class Sample
{
private:
double d_val;
double* d_ptr;
};

class Test
{
private:
int i_val;
int* i_ptr;
Sample obj;
};

Suppose I allocate
Test* t = new Test();

Since I have mentioned 'new Test()' instead of just 'new Test',
will this statement set
t->i_val to zero, t->i_ptr to null pointer, t->obj.d_val to 0.0,
t->obj.d_ptr to null pointer ?

What does the standard say in this regard ?

I just asked this question to my local C++ guru this morning, and he
said that no, these members are not implicitely initialized. You have
to do it yourself. The problem is that "[p]rimitive type member
variable like int, float etc does not have any constructors, so they
are just initialized with an undefined initial value which is often a
garbage."

Note that you should probably always define a constructor (perhaps
private), to let other objects use your class for its member and have
it automatically initialized with default values.
 
A

Andrey Tarasevich

Consider the following classes without ctors.

class Sample
{
private:
double d_val;
double* d_ptr;
};

class Test
{
private:
int i_val;
int* i_ptr;
Sample obj;
};

Suppose I allocate
Test* t = new Test();

Since I have mentioned 'new Test()' instead of just 'new Test',
will this statement set
t->i_val to zero, t->i_ptr to null pointer, t->obj.d_val to 0.0,
t->obj.d_ptr to null pointer ?

What does the standard say in this regard ?

The original C++ standard (C++98) says that the data members of your
object will remain uninitialized. Your object has a non-POD class type,
and in the original C++ standard the '()' initializer for such types
causes a constructor call. Since the constructors in your code do
absolutely nothing, the data will remain uninitialized. I.e. there's no
difference between doing 'new Test' or 'new Test()'.

Note, that it you declare all data members as 'public', the types will
become POD and '()' initializer will cause zero-initialization for all
data members, just like you describe.

The current C++ standard (post-TC1) is different in this regard though.
The '()' initializer causes the so called "value-initialization" being
applied to your object. And since your object has no user-declared
default constructor, in this case value-initialization will lead to
zero-initialization of all data-members.
 
J

Juha Nieminen

Pascal said:
"[p]rimitive type member
variable like int, float etc does not have any constructors

That's not true. C++ defines constructors for them because else it
would be very difficult to create many template functions/classes which
handle variables with default values.

This is completely valid:

int i = int();

The rhs basically creates a nameless int and calls its default
constructor (which initializes it to 0). This value is then assigned to
'i'. (Naturally the compiler will optimize all this.)

This is also completely valid:

void foo(int var);

foo(int());

(It creates a nameless temporary of type int, constructs it with its
default constructor, and gives it as parameter to foo.)

Why would anyone want to do that? Why not just do "int i = 0;" and
"foo(0);"? Well, the reasoning behind this becomes clearer with templates:

template<typename T>
void foo()
{
T var = T();
...
}

This will work even if T is of type int (or any other primitive type).
 
A

Andrey Tarasevich

Juha said:
Pascal said:
"[p]rimitive type member
variable like int, float etc does not have any constructors

That's not true.

No, that's true.
C++ defines constructors for them because else it
would be very difficult to create many template functions/classes which
handle variables with default values.

No, non-class types in C++ have no constructors. That's how it is
defined by the official language specification.

Alternative sources might decide to follow a different terminological
approach, deviating from the official terminology for one reason or
another. For example, Stroustrup's TC++PL book is known to state that
scalar types have constructors (apparently, for the sake of simplicity).
This is completely valid:

int i = int();

The rhs basically creates a nameless int and calls its default
constructor (which initializes it to 0).

No (once again, in the official terminology).

The 'int()' expression is a functional-style cast to type 'int' with an
empty set of arguments. Such a case in C++ language produces a
default-initialized unnamed temporary object of type 'int'.
Default-initialization for type 'int' means zero-initialization. That's
it. Note, that nowhere in this description any constructors are mentioned.

Your description, however, is easy to prove wrong. If type 'int' had a
default constructor, the 'int i;' declaration for an automatic variable
would call that constructor and zero-initialize the variable. This
doesn't happen. The same can be said about objects created with 'new
int'. Of course, you can explain this as some kind of exception from the
general rule, but, once again, this will be a non-standard view of the
program behavior.
This is also completely valid:

void foo(int var);

foo(int());

This is the same thing as the previous example.
(It creates a nameless temporary of type int, constructs it with its
default constructor, and gives it as parameter to foo.)

It does create a nameless temporary, but no "default constructors" are
involved here. Once again, in C++ only class types can have constructors.
Why would anyone want to do that? Why not just do "int i = 0;" and
"foo(0);"? Well, the reasoning behind this becomes clearer with templates:

template<typename T>
void foo()
{
T var = T();
...
}

This will work even if T is of type int (or any other primitive type).

True. But the generic concept that is used here is called
_initialization_, not _construction_. What we observe here is that
different (almost all) types can be _initialized_ with '()'. The
semantics of that initializer is different for different types. And only
for class types it might result in a constructor call (not for all class
types, BTW).
 
A

Alexander Dong Back Kim

Pascal said:
"[p]rimitive type member
variable like int, float etc does not have any constructors

That's not true. C++ defines constructors for them because else it
would be very difficult to create many template functions/classes which
handle variables with default values.

This is completely valid:

int i = int();

The rhs basically creates a nameless int and calls its default
constructor (which initializes it to 0). This value is then assigned to
'i'. (Naturally the compiler will optimize all this.)

This is also completely valid:

void foo(int var);

foo(int());

(It creates a nameless temporary of type int, constructs it with its
default constructor, and gives it as parameter to foo.)

Why would anyone want to do that? Why not just do "int i = 0;" and
"foo(0);"? Well, the reasoning behind this becomes clearer with templates:

template<typename T>
void foo()
{
T var = T();
...

}

This will work even if T is of type int (or any other primitive type).

May I ask what compiler are you using?

cheers,
Alex
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top