initializer_lists


Concept: initializer lists in class constructors

An initializer list in C++ is a mechanism used in constructors to initialize class members before the constructor body executes. It provides a way to directly initialize members, potentially improving performance and allowing initialization of const members and references.

Key Characteristics

Example 1: Basic Usage of Initializer List

#include <iostream>
#include <string>

class Person {
private:
    std::string name;
    int age;
    const double height;

public:
    // Constructor using initializer list
    Person(const std::string& n, int a, double h)
        : name(n), age(a), height(h) {
        std::cout << "Person constructed" << std::endl;
    }

    void display() const {
        std::cout << name << " is " << age << " years old and " 
                  << height << "m tall." << std::endl;
    }
};

int main() {
    Person person("Alice", 30, 1.65);
    person.display();

    return 0;
}

Explanation:

Example 2: Initializer List with Default Member Initializers

#include <iostream>
#include <string>

class Car {
private:
    std::string brand;
    std::string model;
    int year = 2023;  // Default member initializer
    double price;

public:
    // Constructor using initializer list and default member initializer
    Car(const std::string& b, const std::string& m, double p)
        : brand(b), model(m), price(p) {
        std::cout << "Car constructed" << std::endl;
    }

    // Constructor that overrides the default year
    Car(const std::string& b, const std::string& m, int y, double p)
        : brand(b), model(m), year(y), price(p) {
        std::cout << "Car constructed with specified year" << std::endl;
    }

    void display() const {
        std::cout << year << " " << brand << " " << model 
                  << " priced at $" << price << std::endl;
    }
};

int main() {
    Car car1("Toyota", "Corolla", 25000.0);
    car1.display();

    Car car2("Honda", "Civic", 2022, 23000.0);
    car2.display();

    return 0;
}

Explanation:

Example 3: Initializer List with Delegating Constructors (C++11)

#include <iostream>
#include <string>

class Employee {
private:
    std::string name;
    int id;
    double salary;

public:
    // Primary constructor
    Employee(const std::string& n, int i, double s)
        : name(n), id(i), salary(s) {
        std::cout << "Primary constructor called" << std::endl;
    }

    // Delegating constructor
    Employee(const std::string& n, int i)
        : Employee(n, i, 50000.0) {  // Calls the primary constructor
        std::cout << "Delegating constructor called" << std::endl;
    }

    void display() const {
        std::cout << name << " (ID: " << id << ") earns $" << salary << std::endl;
    }
};

int main() {
    Employee emp1("Bob", 1001, 60000.0);
    emp1.display();

    Employee emp2("Alice", 1002);
    emp2.display();

    return 0;
}

Explanation:

Example 4: Initializer List with Inheritance

#include <iostream>
#include <string>

class Animal {
protected:
    std::string species;
    int age;

public:
    Animal(const std::string& s, int a) : species(s), age(a) {
        std::cout << "Animal constructed" << std::endl;
    }

    virtual void makeSound() const = 0;
};

class Dog : public Animal {
private:
    std::string breed;

public:
    Dog(const std::string& b, int a)
        : Animal("Canis lupus familiaris", a), breed(b) {
        std::cout << "Dog constructed" << std::endl;
    }

    void makeSound() const override {
        std::cout << "Woof!" << std::endl;
    }

    void display() const {
        std::cout << breed << " dog, age " << age << std::endl;
    }
};

int main() {
    Dog myDog("Labrador", 5);
    myDog.display();
    myDog.makeSound();

    return 0;
}

Explanation:

Additional Considerations

  1. Order of Initialization: Members are initialized in the order they are declared in the class, not the order in the initializer list.

  2. Performance: Initializer lists can be more efficient than assigning values in the constructor body, especially for complex types.

  3. Const and Reference Members: These must be initialized in the initializer list as they cannot be assigned to after construction.

  4. Default Member Initializers: C++11 introduced default member initializers, which can be overridden in the constructor's initializer list.

  5. Delegating Constructors: C++11 allows constructors to delegate to other constructors of the same class using initializer lists.

Summary

Initializer lists in C++ constructors are a powerful feature for member initialization:

  1. They allow direct initialization of members before the constructor body executes.
  2. Essential for initializing const members, reference members, and base classes.
  3. Can improve performance compared to assignments in the constructor body.
  4. Support delegating constructors and work well with inheritance.

Key points to remember:

Best practices:

Initializer lists are a fundamental feature in C++ that contribute to writing more efficient and maintainable code, especially when dealing with complex class hierarchies and const correctness.

Related

Previous Page | Course Schedule | Course Content