liveBook · Manning

Default constructor

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

A default constructor is a constructor that can initialize an object without requiring caller-supplied arguments.

A default constructor initializes an object without caller-supplied arguments. C++ may supply one when no constructor is written, but supplying another constructor prevents automatic generation. Treat the generated constructor as a convenience, not proof that the resulting object has meaningful state. section 2.4 section 7.3

Use a default constructor deliberately:

  • Use `= default` when the compiler-generated behavior is correct and making that intent explicit improves readability. section 2.4
  • Use `= delete` when an operation such as assignment must not be available, rather than hiding an undeclared member privately. section 2.4
  • Do not use a default constructor merely to create an object that must later receive essential data through setters. section 7.8 section 10.2
  • Make construction establish the class invariant: initialize every instance variable meaningfully, reject invalid input, or prevent construction. section 7.3 section 10.2

From hidden operations to explicit intent

A `Container` can support default construction and copying while rejecting assignment. The modern declaration communicates both decisions directly: `Container() = default;` and `Container& operator=(const Container&) = delete;`. This is clearer than writing an empty default constructor and hiding assignment privately. section 2.4

Listing 2.8 A simple class with defaulted and deleted members
class Container {
private:
    std::vector<int> values;
public:
    Container() = default;                                      #1
    Container(const Container& o) : values(o.values) {}
    Container& operator=(const Container& o) = delete;          #2
    void add(int n) { values.push_back(n); }
};
 
int main() {
    Container c1;
    c1.add(42);
    Container c2(c1);
    // c2 = c1;                                                 #3
    return 0;
}

Compare explicit defaulting and deletion with the older handwritten-and-hidden-member approach. section 2.4

A default object can be invalid or meaningless

A `Person p1;` created without a programmer-supplied constructor may contain an empty `name` and an undefined built-in `age`. Requiring a name and validated age during construction prevents callers from using a partially initialized object. If construction cannot establish valid state, throw an exception instead of relying on a later validity check. section 7.8 section 10.2

Listing 10.2 Throwing exceptions for construction failures
class Person {
private:
    std::string name;
    int age;
    static const std::string& validateName(const std::string& name) { #1
        if (name.empty())
            throw std::invalid_argument("name must not be empty");
        return name;
    }
    static int validateAge(int age) {                                 #2
        if (age < 0)
            throw std::out_of_range("age must be non-negative");
        return age;
    }
public:
    Person(const std::string& name, int age) : 
       name(validateName(name)), age(validateAge(age)) {}             #3
    int getAge() const { return age; }
    const std::string& getName() const { return name; }
    bool isValid() const { return age > -1; } 
};
 
int main() {
    // Person sally("Sally");                                         #4
    Person sally("Sally", 27);
    std::cout << sally.getName() << " is " << sally.getAge() 
        << " years old\n";
 
    Person brian("Brian", -1);                                        #5
    std::cout << brian.getName() << " is " << brian.getAge() 
        << " years old\n";
    return 0;
}

Shows constructor validation that rejects an empty name or negative age before the object becomes usable. section 10.2

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

How deep it goes
Explains generation rules, initialization consequences, invariant failures, and exception-based correction, stopping short of compiler implementation internals.
Examples
Uses Container declarations, Person initialization cases, arrays, vectors, setters, and validating constructors as concrete examples.
What it assumes
Assumes basic C++ classes and object creation while teaching compiler-generated members, initialization behavior, and constructor validation.
What you can do after
Evaluate whether default construction preserves valid state, then apply =default, =delete, required arguments, or constructor exceptions.
How it connects
Connects default constructors with copy constructors, move constructors, destructors, assignment operators, class invariants, and exceptions.

Also explained in

Compare how 3 books explain default constructor →

Related concepts

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.