Question regarding pointer initialization

Hi all,
I have one simple question here.
I know that the class primitive members are automatically initialized to 0 or "" if they are string.
But is this the same for the pointers ?

Are they automatically initialized to 0 ? Or I should explicitly set them to NULL or 0 in the constructor.

Thank you in advance
Class members are default constructed unless they are explicitly constructed in some other way.

The default constructor for all POD-types (pointers included) does nothing.

You need to explicitly set integers, floats, pointers, etc to zero in your constructor.

Three ways to do this: (the first way is the best way, but most people do it the second or third way)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo {
   int x;
  public:
   Foo() : x() {}  // Assigns zero to x
};

class Foo {
   int x;
  public:
   Foo() : x(0) {} 
};

class Foo {
   int x;
  public:
   Foo() { x = 0; }  
};


jsmith, I'm confused. I thought that you said that the default constructor for all POD types does nothing but in your first example you indicate that manually invoking the constructor for an int sets it to zero. Is that not the default constructor?
Basic types get the value present at the memory address in which are stored if the constructor isn't called explicitly and if they aren't global variables
I see. Thank you very much. :)
Well, I guess this

Foo() : x() {} // Assigns zero to x

will assign 0 to x.
I'm trying to find the language in the C++ std that confirms what jsmith and bazzy are saying but I cannot find it. I understand what they are saying but not sure where to find the documentation that proves that it is true. I've always used the second form of initialization as in jsmith's example because I can find no documentation that describes how the first part of the example is required to work.
Yes, that's correct. This had to be added to the language to solve the following problem (using an example):

1
2
3
4
5
6
7
8
9
template< typename T, typename Iter >
T add( Iter first, Iter last )
{
  // What should this line be? : T sum = 0;? 
  for( ; first != last; ++first )
     sum += *first;

  return sum;
}


Now if T is of integral or floating point type, T sum = 0; is fine. But what if T is a std::string?
Then

 
std::string sum = 0;


is a compile error since std::strings cannot be constructed from an int.

But clearly we have to initialize sum to 0 for numeric types, the empty string for string types,
etc.

How? The answer is that when you [i]explicitly invoke the default constructor of a POD-type,
it has the effect of assigning zero.

That is:

 
int x = int();  // x = 0; 


Note that you have to do it that way, and not

 
int x();


because that declares a function named x that takes no parameters and returns an int.

So I say that my first example in my original post is best because it is guaranteed to "do the right
thing" all the time. For example, suppose you had this class:

1
2
3
4
class Foo {
   std::string id;    
   Foo() {};
};


Tomorrow or six months from now or two years from now, if you decide that id should be an int instead of a string, suddenly bad things happen because id, which used to be default constructed to an empty string, is now totally uninitialized. Although the fix is easy enough, the bottom line is that you still had to spend time figuring out what went wrong when you could have avoided the problem in the first place.

For this reason, you should spend the extra few seconds and explicitly initialize all data members of a class, even if that means calling the default constructor.

1
2
3
4
class Foo {
   std::string id;    
   Foo() : id() {};
};


now works regardless of what type id is.


Last edited on
@ kempofighter
It's in there under the Initializers section

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
[Note: since () is not permitted by the syntax for initializer,X a();is not the declaration of an object of class X, but the declaration of a function taking no argument andreturning an X. The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). ]


and a bit more about value-initialization:
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is
called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member
and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized


and a bit about zero-initialization
To zero-initialize an object of type T means:
— if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
— if T is a non-union class type, each nonstatic data member and each base-class subobject is zeroinitialized;
— if T is a union type, the object’s first named data member89) is zero-initialized;
— if T is an array type, each element is zero-initialized;
— if T is a reference type, no initialization is performed.
int x = int(); // x = 0;

How a primitive have constructor ? I though primitives don't have constructors because they are PODs.

Also note that references are not allowed. In addition, a POD type can't have constructors, virtual functions, base classes, or an overloaded assignment operator.
Thanks for posting the examples and text from the std. I was having trouble finding the specific part of the std that would explain this.

@cppuser. Well I guess that the built in types have default constructors which is okay for POD type. POD type can't have user defined constructor and we can't make a user defined constructor for the built in types anyway. That isn't what is being done in the examples. In the examples we are invoking the default constructor which already exists, not one that was defined by the user. That coupled with the explanation from the std about value_type initialization makes a lot of sense. Since template types could be anything there is no one value, such as 0, that would make sense for all types so jsmith's explanation and example really helps clear that up.

This turned out to be a good thread.
Topic archived. No new replies allowed.