I am reading "Accelerated C++" by Andrew Koenig and Barbara E. Moo, and I'm at the chapter about constructors (5.1).
They mention here that
We said that constructors exist to ensure that objects are created with their data members in a sensible state. In general, this design goal means that every constructor should initialize every data member. The need to give members a value is especially critical for members of built-in type. ...
Although we explicityly initialized only midterm
and final
, the other data members are initialized implicitly. Specifically, n
is initialized by the string
default constructor, and homework
is initialized by the vector
default constructor.
The class they are talking about is
class Student_info {
public:
std::string name() const (return n;}
bool valid() const {return !homework.empty();}
std::istream& read(std::istream&);
double grade() const;
private:
std::string n;
double midterm, final;
std::vector<double> homework;
};
and their default constructor is
Student_info::Student_info(): midterm(0), final(0) {}
I would just like to clarify that this means that things like int
and double
where there isn't a std::
before the term will need to be initialized specifically?
That is correct.
But std:: is not what you are looking for.
Any of the fundamental types are not initialized unless you do it explicitly.
So char/int/float/pointers
etc. Also (as noted by Ian below) any class/unions without an explicit constructor will default initialize its members (which means fundamental (and recursively for member s of class/unions without and explicit constructor) that they are left undefined).
A side note:
- This rules applies to automatic and dynamic storage duration objects
- Static and thread storage duration objects are zero initialized.
int
and double
are built-in types, not classes, so they don't have default constructors, and are undefined by default. For example:
int a;
Student_info s;
The syntax for both variables is the same, but the value of a
is undefined, while the value of s
is defined because Student_info s
actually calls the constructor, i.e. Student_info s = Student_info();
.
The author is just trying to show a default constructor where everything is defaulted to the equivalent of 0. For string and vector, those will just be empty. For primitive types such as int and double, the initial value of these primitives during declaration is defaulted to the value that was in memory that variable points to. This does depend on the compiler though
It is not related to std namespace. n and homework are classes, their constructor will be called during the construction of Student_info. But midterm and final are primitive values, there aren't constructors for them. Initialize the primitive member in constructor is not necessary but a good manner.
There is more to it.
1) For primitive or built-in types, implicitly initialized (or compiler initialized) means no-op (does nothing).
2) For primitive or built-in types, explicitly initialized (or initialized by the programmer) is obvious :)
As in your example:
Student_info::Student_info(): midterm(0), final(0) {}
3) For non-primitive types, implicitly initialized (or compiler initialized) means compiler may (or may not) synthesis a constructor for the purpose of initialization.
Usually, a constructor is synthesized by the compiler under the following cases:
a) The non-primitive type is polymorphic or derives from some polymorphic/non-polymorphic types,
b) The non-primitive type has a polymorphic/non-polymorphic member.
Compiler synthesized constructor will usually have code to
a) initialize v-pointer to v-table,
b) call base class constructor,
c) call constructors of members, so on,
basically driven by the definition of non-primitive type.
4) For non-primitive types, explicitly initialized (or initialized by the user supplied constructor) means compiler would make a call to the user defined constructor instead of synthesizing one for the purpose of initialization.
For example, the default constructor defined by the respective non-primitive types (like std::string or std::vector) gets invoked.
**
Note: Compiler may still augment code inside the user-defined
constructor to do some behind-the-scenes initialization as need be
(look at step-3 above for such needs). Such augmented code will always
be inserted before the user-defined code inside the constructor!
**