AUTOSAR C++14 Rule A12-8-4

Конструктор Move не должен инициализировать свои члены класса и базовые классы, используя семантику копирования

Описание

Определение правила

Конструктор перемещения не должен инициализировать свои члены класса и базовые классы с помощью семантики копирования.

Объяснение

В C++ операции перемещения переносят владение ресурсами, а не дублируют сами ресурсы из исходного объекта в целевой объект. Поскольку конструкторы перемещения не дублируют ресурсы, эти конструкторы быстрее, чем конструкторы копирования. Рассмотрим этот код, где объект CopyTarget копируется, и объект MoveTarget сконструирован на перемещение из объекта 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);
	//...
}

При копировании-построении CopyTargetкомпилятор дублирует ресурс Source::BigBook от Source на CopyTarget. После создания копии оба этих объектов имеют копию ресурса BigBook. При построении Movetargetкомпилятор передает право собственности на ресурс Source::BigBook на MoveTarget. Поскольку move-construction не дублирует ресурс физически, это быстрее, чем copy-construction.

Move-construction является стратегией оптимизации. Вы ожидаете, что move-construction будет дешевле и быстрее, чем copy-construction. Инициализирующие копирование представители данных и базовые классы могут сделать конструктор перемещения медленным и неэффективным, что снижает эффективность программы. Разработчики ожидают, что move-construction использует только семантику перемещения. Неожиданное использование семантики копирования в конструкторах перемещения может привести к утечкам ресурсов и несогласованности в будущем развитии. При создании конструкторов перемещения инициализируйте представители данных и базовые классы с помощью семантики перемещения. Можно копировать-инициализировать скалярные представители данных, не нарушая это правило.

Вы можете использовать std::move() для реализации семантики перемещения в коде. Когда вы используете std::move() чтобы переместить объекты, объявите объекты или представители данных без квалификатора const. Для получения дополнительной информации смотрите AUTOSAR C++14 Rule A18-9-3.

Реализация Polyspace

Когда конструктор перемещения не использует семантику перемещения для инициализации нескалярных представителей данных и базовых классов, Polyspace® помечает его объявление. Например, если конструктор перемещения инициализирует базовый класс с помощью конструктора по умолчанию вместо конструктора перемещения, Polyspace помечает объявление конструктора перемещения.

Поиск и устранение проблем

Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».

Примеры

расширить все

В этом примере показано, как флаги Polyspace перемещают конструкторы, которые используют copy-initialization и конструкцию по умолчанию.

#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;
};

  • Конструктор перемещения класса BigData инициализирует представитель данных BigBook при помощи семантики перемещения. Конструктор перемещения инициализирует скалярный представитель Length при помощи семантики копирования. Этот конструктор перемещения совместим, потому что копирование скалярных представителей данных не нарушает это правило.

  • Конструктор перемещения класса slowBigdata инициализирует представителей данных с помощью семантики копирования. Этот конструктор перемещения нарушает правило, и Polyspace помечает объявление конструктора перемещения.

  • Конструктор перемещения класса BigData2 вызывает конструктор по умолчанию базового класса, что может сделать код медленным и неэффективным. Polyspace помечает объявление этого конструктора перемещения. Конструктор перемещения класса BigData3 вызывает конструктор перемещения базового класса. Этот конструктор перемещения соответствует этому правилу.

Проверяйте информацию

Группа: Специальные функции представителей
Категория: Необходимый, Автоматизированный
Введенный в R2020b