Move operation uses copy

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

Описание

Этот дефект повышен, если все эти условия верны:

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

  • Операции пересылки для базового класса или элементов данных доступны.

  • Базовый класс или элементы данных являются более дорогими, чтобы скопировать, чем переместиться.

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

class wrapper{
	//...
	wrapper(wrapper&& rhs): data(rhs.data){
		//...
	}

	private:
	std::string data;
}

Риск

Разработчики часто принимают, что операции пересылки являются более дешевыми, чем операции копии. Они используют операции пересылки при контакте с большими ресурсами, которые являются дорогими, чтобы скопировать. Непреднамеренно не использующие вызовы std::move может заставить конструктора перемещения или оператор присваивания перемещения копировать элементы данных и базовые классы, делая код неэффективным. Поскольку такие неожиданные операции пересылки скомпилировали и запустили правильно, пропуск стимулирования неэффективности std::move может затруднить, чтобы обнаружить.

Исправление

Чтобы зафиксировать этот дефект, используйте std::move перемещать базовые классы и элементы данных класса. Как лучшая практика, используйте неявного конструктора перемещения по умолчанию и переместите оператор присваивания путем установки их как =default. Вместо ресурсов сырых данных управления используйте умные контейнеры, чтобы позволить операциям пересылки по умолчанию переместить ресурсы правильно.

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

Примеры

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

#include <memory>
#include <string>
#include <utility> 

class ManagerInterface;
// ...
class UtilInterface
{
public:
	// ...
	UtilInterface( UtilInterface&& other )
	  : m_name( other.m_name ), //Noncompliant
	    m_manager( other.m_manager ) //Noncompliant
	{/**/}
	UtilInterface& operator=( UtilInterface&& other )
	{
		m_name = other.m_name; //Noncompliant
		m_manager = other.m_manager; //Noncompliant
		return *this;
	}
	// ...
private:
	// ...
	std::string m_name;
	std::shared_ptr< ManagerInterface > m_manager;
	// ...
};

В этом примере, операциях пересылки класса UtilInterface скопируйте элемент данных вместо того, чтобы переместить их при помощи std::move. Polyspace отмечает неожиданные операции копии.

Коррекция

Чтобы зафиксировать дефект, используйте std::move перемещать элементы данных.

#include <memory>
#include <string>
#include <utility> 

class ManagerInterface;
// ...
class UtilInterface
{
public:
	// ...
	UtilInterface( UtilInterface&& other )
	  : m_name( std::move(other.m_name) ), //Compliant
	    m_manager( std::move(other.m_manager) ) //Compliant
	{}
	UtilInterface& operator=( UtilInterface&& other )
	{
		m_name = std::move(other.m_name); //Compliant
		m_manager = std::move(other.m_manager); //Compliant
		return *this;
	}
	// ...
private:
	// ...
	std::string m_name;
	std::shared_ptr< ManagerInterface > m_manager;
	// ...
};
Коррекция

Другой метод фиксации этого дефекта должен объявить оператор присваивания перемещения и конструктора перемещения как =default.

#include <memory>
#include <string>
#include <utility> 

class ManagerInterface;
// ...
class UtilInterface
{
public:
	// ...
	UtilInterface( UtilInterface&& other ) = default;//Compliant
	UtilInterface& operator=( UtilInterface&& other ) = default;//Compliant
	// ...
private:
	// ...
	std::string m_name;
	std::shared_ptr< ManagerInterface > m_manager;
	// ...
};

Информация о результате

Группа: Производительность
Язык: C++
Значение по умолчанию: Off
Синтаксис командной строки: MOVE_OPERATION_USES_COPY
Удар: Средняя
Введенный в R2021b