The following program is in 5 files. The output is 0 32, instead of 14 32 and therefore an object is constructed without calling the constructor. How is this possible?
character.h:
#ifndef CHARACTER_H
#define CHARACTER_H
class Character
{
public:
Character() {}
class Settings
{
public:
int size_;
Settings():
size_(14)
{}
};
const static Settings DEFAULT_SETTINGS;
};
#endif // CHARACTER_H
character.cpp:
#include "character.h"
const Character::Settings Character::DEFAULT_SETTINGS;
word.h
#ifndef WORD_H
#define WORD_H
#include <iostream>
#include "character.h"
class Word
{
public:
Word() {}
class Settings
{
public:
Character::Settings characterSettings_;
int length_;
Settings():
length_(32)
{
characterSettings_ = Character::DEFAULT_SETTINGS;
}
};
static const Settings DEFAULT_SETTINGS;
void write(Settings settings = DEFAULT_SETTINGS) // this default parameter is
// constructed without a
// constructor call
{
std::cout << settings.characterSettings_.size_ << std::endl;
std::cout << settings.length_ << std::endl;
}
};
#endif // WORD_H
word.cpp
#include "word.h"
const Word::Settings Word::DEFAULT_SETTINGS;
main.cpp
#include "word.h"
int main(int argc, char *argv[])
{
Word member;
member.write();
return 1;
}
That’s called the static initialization fiasco. Basically there is no fixed order on the execution of the constructors for variables with static duration defined in different translation units. In this particular case the
Word::DEFAULT_SETTINGShas been constructed before theCharacter::DEFAULT_SETTINGSand thus has read the0value that variables of static duration have before being actually initialized. If you want to see something interesting, dump the contents ofCharacter::DEFAULT_SETTINGSand you will see that strangely enough it is14