Main Content

AUTOSAR C++14 Rule A12-8-4

Move constructor shall not initialize its class members and base classes using copy semantics

Since R2020b

Description

Rule Definition

Move constructor shall not initialize its class members and base classes using copy semantics.

Rationale

In C++, move operations transfer the ownership of resources rather than duplicating the resources themselves from a source object to a target object. Because move constructors do not duplicate resources, these constructors are faster than copy constructors. Consider this code where the object CopyTarget is copy-constructed and the object MoveTarget is move-constructed from the object Source.

class BigData{
	//...
	BigData(BigData&&){  //Move Constructor
		//...
	} copy constructed
	BigData(const BigData&){  //Copy Constructor
		//...
	}
private:
	std::map<int, std::string> BigBook;
};

int main(){
	BigData Source;
	BigData CopyTarget = Source;
	BigData Movetarget = std::move(Source);
	//...
}

When copy-constructing CopyTarget, the compiler duplicates the resource Source::BigBook from Source to CopyTarget. After the copy-construction, both of these objects have a copy of the resource BigBook. When move-constructing Movetarget, the compiler transfers the ownership of the resource Source::BigBook to MoveTarget. Because move-construction does not duplicate the resource physically, it is faster than copy-construction.

Move-construction is an optimization strategy. You expect that move-construction is cheaper and faster than copy-construction. Copy-initializing data members and base classes can make a move constructor slow and inefficient, which reduces program performance. Developers expect that move-construction uses move semantics only. Unexpectedly using copy semantics in move constructors might introduce resource leaks and inconsistency in future development. When authoring move constructors, initialize data members and base classes by using move semantics. You can copy-initialize scalar data members without violating this rule.

You might use std::move() to implement move semantics in your code. When you use std::move() to move objects, declare the objects or data members without the qualifier const. For more information, see AUTOSAR C++14 Rule A18-9-3.

Polyspace Implementation

When a move constructor does not use move semantics to initialize nonscalar data members and base classes, Polyspace® flags its declaration. For instance, if a move constructor initializes the base class by using the default constructor instead of the move constructor, Polyspace flags the declaration of the move 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

This example shows how Polyspace flags move constructors that uses copy-initialization and default construction.

#include<cstdint>
#include<string>
#include<map>
#include <vector>
class BigData{
public:
	BigData()=default;
	//...
	BigData(BigData&& oth): //Compliant
	BigBook(std::move(oth.BigBook)),  
	Length(oth.Length)	
	{  
		//...
	} 
	
private:
	std::map<int, std::string> BigBook;
	int Length;
};

class slowBigData{
	//...
	slowBigData(slowBigData&& oth): //Noncompliant
	BigBook(oth.BigBook),  
	Length(oth.Length)	           
	{  
		//...
	} 
	
private:
	std::map<int, std::string> BigBook;
	int Length;
};

class BigData2: public BigData{
	//...
	BigData2(BigData2&& oth):BigData() //Noncompliant
	
	{  
		BigVector = std::move(oth.BigVector);
		//...
	} 
	
private:
	std::map<int, std::string> BigBook;
	std::vector<int> BigVector;
	int Length;
};

class BigData3: public BigData{
	//...
	BigData3(BigData3&& oth):BigData(std::move(oth)) //Compliant
	
	{  
		str = std::move(oth.str);
		//...
	} 
	
private:
	std::map<int, std::string> BigBook;
	int Length;
	std::string str;
};

  • The move constructor of the class BigData initializes the data member BigBook by using move semantics. The move constructor initializes the scalar member Length by using copy semantics. This move constructor is compliant because copying scalar data members does not violate this rule.

  • The move constructor of the class slowBigdata initializes the data members by using copy semantics. This move constructor violates the rule and Polyspace flags the declaration of the move constructor.

  • The move constructor of the class BigData2 invokes the default constructor of the base class, which might make the code slow and inefficient. Polyspace flags the declaration of this move constructor. The move constructor of the class BigData3 invokes the move constructor of the base class. This move constructor is compliant with this rule.

Check Information

Group: Special member functions
Category: Required, Automated

Version History

Introduced in R2020b