exponenta event banner

Правило AUTOSAR C++ 14 A6-2-1

Операторы назначения перемещения и копирования должны либо перемещать, либо соответственно копировать базовые классы и элементы данных класса без каких-либо побочных эффектов

Описание

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

Операторы назначения перемещения и копирования должны либо перемещать, либо соответственно копировать базовые классы и элементы данных класса без каких-либо побочных эффектов.

Объяснение

При использовании операторов перемещения и копирования назначения предполагается, что операция перемещает или копирует исходный объект в целевой объект без каких-либо побочных эффектов. Если операторы назначения перемещения или копирования класса создают побочные эффекты, инвариант объекта может изменяться во время назначения перемещения или копирования. Рассмотрим этот код, когда несколько объектов класса C присваиваются друг другу.

class C{
	//...
	C& operator=(const C& oth) { 
		value = oth.value / 2;
		return *this;		
	}
public:
	int value;
};

int main(){
	C a, b, c; 
	a.value = 48;
	// …
	b = a; // b.m = 24  
	c = b; // c.m = 12
	a = c; // a.m = 6
}
Во время каждого присвоения копии value в целевом объекте становится половиной value в исходном объекте. После трех последовательных операций присвоения копий, a.value становится 6, что неожиданно. Алгоритмы ожидают операторы перемещения и копирования назначения, которые не изменяют инвариант объекта. Если операторы перемещения или копирования назначения класса имеют побочные эффекты, изменяющие инвариант объекта, использование библиотек алгоритмов, таких как библиотека стандартных шаблонов (STL), может привести к неожиданным результатам.

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

Для поддержания оптимальной и надежной производительности во время перемещения и копирования назначений выполните только следующие операции в операторах перемещения и копирования назначений:

  • Копирование или перемещение элементов данных и базовых классов.

  • Возврат указателя *this.

  • По возможности переведите объект moved-from в допустимое состояние.

Избегайте лишнего кода, который добавляет несвязанные побочные эффекты или накладные расходы на производительность.

Внедрение Polyspace

В теле оператора назначения копирования или перемещения Polyspace ® не помечает следующие операции:

  • Копирование или перемещение назначений.

  • Реляционные операции или операции сравнения.

  • Изменение исходного объекта в операции перемещения.

  • Вызовы функции std::swap или эквивалентный определяемый пользователем noexcept функции подкачки. Polyspace идентифицирует функции, которые эти сигнатуры как функции подкачки: void T::swap(T&) или void [N::]swap(T&, T&). Первая сигнатура представляет функцию-член класса T для этого требуется один аргумент. Вторая сигнатура представляет не являющуюся членом или статическую функцию в пространстве имен N для этого требуется два аргумента. Имя swap может быть без учета регистра и префиксом или постфиксированным подчеркиванием.

  • Присвоение и изменение static переменные.

Polyspace помечает любые другие операции в операторе назначения копирования или перемещения как нежелательный побочный эффект. Например, вызов определяемой пользователем функции свопа считается нежелательным побочным эффектом, если функция свопа не является noexcept. Аналогичное правило для конструктора копирования и перемещения см. в разделе AUTOSAR C++14 Rule A12-8-1.

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

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

Примеры

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

Этот код показывает, как флаги Polyspace перемещают и копируют операторы назначения, которые имеют побочные эффекты.

#include<cstdint>
#include<iostream>
class B
{
public:
	B() : ptr(0) {}
	B& operator=(B&& oth) //Noncompliant
	{

		if(&oth == this) {
			return *this;
		}
		ptr = std::move(oth.ptr); 
		std::cout<<"Moved";
		return *this;
	}

private:
	std::int32_t* ptr;
};
class C
{
public:
	C(int t=0) : x(t) {}
	C& operator=(const C& oth)  // Noncompliant
	{
		if(&oth == this) {
			return *this;
		}
		x = oth.x % 2;         // This operation produces side-effect
		count++; //Not a side effect
		return *this;
	}

private:
	std::int32_t x;
	static std::int32_t count;

};
class D
{
public:
	D(const D&) = default;
	D(D&&) = default;

	D& operator=(const D& oth) & {     // Noncompliant
		D tmp(oth);
		swap(tmp);
		return *this;
	}
	
	// Member function swap
	void swap(D& rhs)  {
		//...
	}

private:
	std::int32_t x;
};
  • В качестве побочного эффекта оператор назначения перемещения класса B печатает строку в выходном потоке. Этот побочный эффект добавляет к операции перемещения накладные расходы на производительность. Если это утверждение std::cout<<"Moved" вызывает исключение, выполнение кода может неожиданно прекратиться. Polyspace помечает оператор назначения перемещения и выделяет оператор.

  • Оператор назначения копирования C изменяет элемент данных x исходного объекта. Этот побочный эффект добавляет накладные расходы на производительность. Неожиданное изменение элементов данных во время операций перемещения и копирования может привести к несовместимости кода с библиотекой стандартных шаблонов и возникновению ошибок во время разработки. Polyspace помечает оператор назначения копирования и выделяет оператор x = oth.x % 2. Приращение статической переменной count не является побочным эффектом.

  • Оператор присвоения копии класса D вызывает определяемую пользователем функцию подкачки _swap_. Эта функция подкачки не является noexcept. Если исключение создано из _swap_, исключение является неожиданным побочным эффектом оператора назначения копирования. Polyspace помечает конструктор копирования как несоответствующий этому правилу. Использовать пользовательские функции подкачки, которые noexcept.

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

Группа: выписки
Категория: Обязательно, Автоматизировано
Представлен в R2020b