Main Content

Expensive member initialization

You assign values to class members in the constructor body instead of constructing members using a member initializer list

Since R2023b

Description

Polyspace® reports this defect when you initialize a class member by assigning a value to the class member in the constructor body. Consider this class definition:

class A
{
  public:
    A(std::string s) //default constructed
    {
      str = std::move(s);   //assigned a value                   
    }

  private:
    std::string str;
};
To assign a value to the class member A::str, this code first constructs the string s and then immediately assigns s to A::str. This immediate reassignment is inefficient and Polyspace reports a defect.

Polyspace does not report this defect if the class member is trivial to copy. To check if a type is trivially copyable, use the function std::is_trivially_copyable. For the syntax if this function, see is_trivially_copyable.

Risk

Initializing a class member as shown in the preceding code requires calling the constructor and then the assignment operator of std:: string. Because the constructed value is immediately assigned, the construction is unnecessary. Because the inefficient code compiles and behaves correctly, you might not detect the inefficiency.

Fix

To fix the expensive member initialization, avoid assigning values to class members in the constructor body. Instead, initialize the class members by using an initializer list. For instance, you can improve the efficiency of the preceding code:

class A
{
  public:
    A(std::string s) : str(std::move(s)) //str is constructed 
                              // directly with the desired value
    {
      //...
    }

  private:
    std::string str;
};

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

In this example, the class myClass manages an unordered set of strings. In the class, the private member obj is assigned a value in the body of the constructor. Such an initialization is inefficient. Polyspace reports a defect.

#include <string>
#include <unordered_set>
#include <vector>

typedef std::unordered_set<std::string> Type1;

class myClass{
	
	private:
	Type1 obj;
	public:
	myClass(Type1 in){
		obj = std::move(in); //Defect
	}
};
Correction — Use Initializer List

To fix this defect, initialize the class member obj by using an initializer list. Avoid assigning values to class members in the class constructor body.

 #include <string>
#include <unordered_set>
#include <vector>

typedef std::unordered_set<std::string> Type1;

class myClass{
	
	private:
	Type1 obj;
	public:
	myClass(Type1 in): obj(std::move(in)){ //No Defect
		//...
	}
};

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_MEMBER_INITIALIZATION
Impact: Low

Version History

Introduced in R2023b