Default constructor invocation

I will appreciate if someone explains:

* why is this wrong:
ObjectType var(); // error
while these are right:
1
2
3
ObjectType var; // ok
ObjectType var = ObjectType; // error
ObjectType var = ObjectType(); // ok 
?

* is anyone of the following more correct?
1
2
ObjectType* pvar = new ObjectType();
ObjectType* pvar = new ObjectType;


* is it safe for all types (incl. the built-in) to invoke 0-arg constructor like this:
1
2
Type var;
Type* pvar = new Type();
?
The first one is wrong because it could be forward declaration for a function var that takes no parameters and returns an ObjectType. The compiler parses it as such and that is commonly known as C++'s Most Vexing Parse. The term was coined in Scott Meyer's book, Effective C++.

Using new dynamically allocates memory for the objects, which will later need deleted. It is not wrong but it is not the same as the others.

It is safe to "default construct" built-in types. It actually initializes their value to 0, as opposed to leaving them uninitialized.
Last edited on
thanks moorecm,
funny, I now understand immediately about the first, but it didn't come in my mind :\

But still it's not clear weather
new ObjectType;
or
new ObjectType();
is ever any different or not?
They are the same as long as ObjectType is not a POD type--it runs the default constructor.
If ObjectType is a POD type (int, long, unsigned, char, bool, float, etc, etc) then the first
one allocates a new variable and leaves it uninitialized whereas the second one will initialize
the value to 0 (for bool this is false).
Hmm, so a POD, which is a class with int-s, will in one case initialize it's int-s to 0, but in the other not?
Edit: actually, what info should I take as reference to sort this out, so I wouldn't have to ask here? (I read three C++ books, but didn't find in any or missed)
Last edited on
A POD-type is a "Plain 'Ol Data" type, which is any non-user defined type.

So char, signed char, unsigned char, int, unsigned int, long, unsigned long,
(long long and unsigned long long if your compiler supports it), bool, and
any pointer type (can be a pointer to anything, including a user defined type).

You might find this answer in the template section of the book. This syntax
was added to the language to solve the following problem:

1
2
3
4
5
6
7
8
9
template< typename T >
class Foo
{
    public:
        Foo() {}

    private:
        T value;
};


If T is not a POD-type, then T's default constructor will initialize value. For example, if T
is a std::string, we know that a default constructed value will be an empty string. Or if
T is a std::vector<int>, we know that a default constructed value will be a vector containing
zero elements.

But what if T is an int? The "default" constructor for int does nothing, leaving value uninitialized.
Ideally we'd like it initialized. The solution is this:

1
2
3
4
5
6
7
8
9
template< typename T >
class Foo
{
    public:
        Foo() : value() {}   // <--- Note the change here

    private:
        T value;
};


This syntax initializes value to the binary equivalent of 0 if T is a POD-type. Otherwise, it runs the
default constructor for T if T is not a POD-type, just like the first example did.

This syntax can also be used on new:

1
2
int* p = new int();   // Set *p to 0
int* p = new int(42);  // Set *p to 42 

Thanks, I understand, just still about what is POD: if you see Wikipedia [1] and it's the same (I guess, is), it says class too can be a POD. Actually my g++ programs have value of uninitialized int-s a 0 because of either a compiler behaviour or some "accident". So I can't understand what happens with a POD struct/class: is there any difference between new classType(); and new classType; or not...

[1] http://en.wikipedia.org/wiki/Plain_old_data_structure
If classType is not one of the POD-types as I've defined the term (ie, it is a class or struct), then in either
case it runs classType's default constructor. If you don't provide a default constructor, then the compiler
gives you one that simply runs the default constructor of each data member in the order declared.

Repeat the above statement for each data member. ie, if the first data member is an int, the default
constructor for int does nothing, and therefore the value is uninitialized. If the first data member is
a std::string, it runs std::string's default constructor.
ok, then last question: how is a compiler's default constructor treating class member of int type: initialize it as int() or leave uninitialized?
leave uninitialized.
I am sorry if i am reinventing the weel. But i am not able to understand what happens in either case.

int *newint1 = new int();

ok.. default constructor is called and 0 is initialised.Does that mean that the below line does not invoke any constructor at all?

int *newint = new int;

Whats happening behind the scenes.. Great question Karlis...
So compiler intrinsic types (int, etc) don't really have constructors at all. The compiler either generates code to
initialize the variable or it doesn't. In the first case, the compiler generates code that writes zero to *newint1.
In the second case, it omits this instruction.
And there is no difference in initialization of a member int, if I use "new myclass;" or "new myclass();"?
no, it runs the default constructor of myclass either way.
Thank you guys... I have one more small doubt..


1
2
3
ObjectType var; // ok
ObjectType var = ObjectType; // error
ObjectType var = ObjectType(); // ok 


Now.. Why the following is ok
ObjectType var; // ok

but the following is errpr

1
2
 ObjectType var = ObjectType; // error
ObjectType var = ObjectType(); // ok 



In other words... What would ve been the problem/issue that prevented c++ from having the following as a valid syntax.


 
 ObjectType var = ObjectType; // error 


Because the grammar of your error line above is:

<type> <identifier> = <type> ;

whereas C++ requires

<type> <identifier> = <value>;

ObjectType, when used alone, is a type.
ObjectType(), is a value (it is a default constructed ObjectType).
Topic archived. No new replies allowed.