liveBook · Manning

Undefined value

As explained in 100 C++ Mistakes and How to Avoid Them

An undefined value is a value whose contents have not been established by the program and therefore have no known intended meaning.

An undefined value is storage whose contents have not been established by the program. In C++, reading an uninitialized built-in variable produces undefined behavior, even though the program may appear to run normally. section 8.11

Prevent undefined values by establishing state before first use:

  • Initialize primitives with a literal, input, or another initialized variable. section 8.11
  • Make constructors initialize every instance variable and establish the class invariant. section 8.11
  • Require necessary arguments instead of allowing clients to initialize required state later. section 8.11
Listing 8.21 A class with an uninitialized built-in instance variable
class Person {
private:
    std::string name;                                         #1
    int age;                                                  #2
public:
    Person(const std::string& name) { this->name = name; }    #3
    void setAge(int age) { this->age = age; }
    friend std::ostream& operator<<(std::ostream&, const Person&);
};
 
std::ostream& operator<<(std::ostream& o, const Person& p) {
    o << p.name << " is " << p.age << " years old";
    return o;
}
 
int main() {
    Person joey("Joey");
    std::cout << joey << '\n';
    return 0;
}

Shows a Person object whose age is declared but never initialized before output, creating undefined behavior. section 8.11

Listing 8.22 A class that insists on arguments for every instance variable
class Person {
private:
    std::string name;
    int age;
public:
    Person(const std::string& name, int age) : 
        name(name), age(age) {}                  #1
    friend std::ostream& operator<<(std::ostream&, const Person&);
};

std::ostream& operator<<(std::ostream& o, const Person& p) {
    o << p.name << " is " << p.age << " years old";
    return o;
}

int main() {
    Person joey("Joey", 27);                     #2
    std::cout << joey << '\n';
    return 0;
}

Replaces delayed setup with constructor arguments and an initializer list, ensuring name and age are initialized together. section 8.11

Validate while initializing

A constructor can pass age through a private validator in its initializer list, rejecting negative input before the object becomes usable.

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains causes, undefined behavior, initialization methods, constructor responsibility, and safer Person-class corrections.
Examples
Uses a Person class with an uninitialized age, then supplies and validates age during construction.
What it assumes
Assumes basic C++ variables and classes while teaching initialization responsibility from first principles.
What you can do after
Build it from scratch by initializing every variable and validating required constructor arguments before use.
How it connects
Connects undefined behavior with primitive initialization, constructors, initializer lists, and class invariants.

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.