exponenta event banner

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