exponenta event banner

Правило AUTOSAR C++ 14 A12-8-4

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

Описание

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

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

Объяснение

В C++ операции перемещения передают владение ресурсами, а не дублируют сами ресурсы из исходного объекта в целевой объект. Поскольку конструкторы move не дублируют ресурсы, эти конструкторы быстрее, чем конструкторы copy. Рассмотрим этот код, где находится объект 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 используется только семантика move. Неожиданное использование семантики копирования в конструкторах перемещения может привести к утечкам ресурсов и несогласованности в будущей разработке. При разработке конструкторов перемещения инициализируйте элементы данных и базовые классы с помощью семантики перемещения. Можно копировать-инициализировать скалярные элементы данных, не нарушая это правило.

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

Внедрение Polyspace

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

Поиск неисправностей

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

Примеры

развернуть все

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

#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