Main Content

MISRA C++:2023 Rule 15.1.4

All direct, non-static data members of a class should be initialized before the class object is accessible

Since R2024b

Description

Rule Definition

All direct, non-static data members of a class should be initialized before the class object is accessible.

Rationale

When the constructor of a class explicitly initializes the class data members completely, the risk of the class being in an invalid state after a successful construction is reduced. Initialize the data members of a class before the constructor body by using data member default initialization, initialization lists, or delegating constructors. For example, in this code, the variable name is default initialized. The first constructor uses an initializer list to initialize the data members before the body of the constructor. The second constructor is a delegating constructor that calls the first constructor to complete the initialization of the data members before the constructor body. This class and its constructors comply with this rule.

#include <string>
class MyClass {
private:
    int age;
    std::string name{"Foo"};  // Default initializer

public:
    
    MyClass(int a, const std::string& n) : age(a), name(n) {}  // Initializer list
    MyClass(const std::string& n) : MyClass(0, n) {} // Delegating constructor
    // Constructor that initializes only age
    MyClass(int a) : age(a) {} // name is default constructed
};
If the data member type has a constructor, use the constructor to initialize the data member before the body of the class constructor. For example, the third constructor that initializes only age and relies on the default constructor of the std::string data member to initialize name is also compliant.

If the class is an aggregate, initialize the class as soon as an object is created. For aggregates, use default member initialization or aggregate initialization. For example, consider the aggregate myAggregate:

class myAggregate{
    public:
    int val;
    std::string str; // Using default constructor    
};
You can default initialize the data members or use their default constructor. Alternatively, initialize the aggregate object during its declaration:
// val is initialized to 0 and str is default constructed
myAggregate obj{}; 

Polyspace Implementation

Polyspace® reports a violation of this rule if either of these conditions are true:

  • An aggregate object is not initialized when it is created.

  • A nondelegating constructor fails to initialize all data members that lack a default constructor.

Troubleshooting

If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

In this example, the constructor of the class MyClass initializes the data members in the constructor body. The objects of this class become accessible before the body of the constructor is executed. Data members of this class are not initialized when the objects are accessible. Polyspace reports a violation.

#include <string>

class MyClass {
private:
    int age;
    std::string name;

public:
    // Constructor that initializes in body
    MyClass(int a, const std::string& n){ // Noncompliant
        age = a;
        name = n;
    }
};

In this example, the class ClassWithDefaultedConstructor has an explicitly defaulted constructor and is an aggregate. Polyspace reports a violation of this rule when the aggregate class is declared without initializing the data member.

class ClassWithDefaultedConstructor {
    public:
        ClassWithDefaultedConstructor() = default;

        int i;
};

void foo(){
    
    ClassWithDefaultedConstructor obj;  // Noncompliant
    ClassWithDefaultedConstructor objinit{};
}

Check Information

Group: Special member functions
Category: Advisory

Version History

Introduced in R2024b