AUTOSAR C++14 Rule 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.

  • Если возможно, устанавливает перемещенный - от объекта до допустимого состояния.

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

Реализация 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