Перемещающее присваивание
Перемещающее присваивание - это специальный оператор присваивания, который вызывается, когда правый операнд является rvalue-ссылкой. В отличие от копирующего присваивания, перемещающее присваивание не копирует ресурсы, а перемещает их из исходного объекта в целевой. Это позволяет избежать дорогостоящего копирования и значительно повысить производительность программы. Оператор принимает один параметр - rvalue-ссылку на объект того же типа.
Перемещающее присваивание обычно используется для классов, которые владеют динамическими ресурсами, такими как память, файловые дескрипторы или сетевые соединения. После перемещения исходный объект остается в допустимом, но неопределенном состоянии.
Синтаксис
class_name& operator=(class_name&& other);
Пример
Давайте создадим класс, который управляет динамическим массивом, и реализуем для него перемещающее присваивание:
#include <iostream>
#include <utility>
using namespace std;
class Array
{
private:
int* data;
size_t size;
public:
Array(size_t s) : size(s), data(new int[s])
{
for (size_t i = 0; i < size; i++)
{
data[i] = 0;
}
}
~Array()
{
delete[] data;
}
Array(const Array& other) : size(other.size), data(new int[other.size])
{
for (size_t i = 0; i < size; i++)
{
data[i] = other.data[i];
}
}
Array& operator=(const Array& other)
{
if (this != &other)
{
delete[] data;
size = other.size;
data = new int[size];
for (size_t i = 0; i < size; i++)
{
data[i] = other.data[i];
}
}
return *this;
}
Array& operator=(Array&& other) noexcept
{
if (this != &other)
{
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
void set(size_t index, int value)
{
if (index < size)
{
data[index] = value;
}
}
int get(size_t index) const
{
return data[index];
}
size_t getSize() const
{
return size;
}
};
int main()
{
Array a(3);
a.set(0, 1);
a.set(1, 2);
a.set(2, 3);
Array b(5);
b = std::move(a);
cout << "b size: " << b.getSize() << endl;
cout << "b values: " << b.get(0) << " " << b.get(1) << " " << b.get(2) << endl;
cout << "a size: " << a.getSize() << endl;
return 0;
}
Результат выполнения кода:
"b size: 3"
"b values: 1 2 3"
"a size: 0"
Пример
Давайте рассмотрим пример с классом, который управляет строкой:
#include <iostream>
#include <cstring>
#include <utility>
using namespace std;
class MyString
{
private:
char* str;
size_t len;
public:
MyString(const char* s) : len(strlen(s)), str(new char[len + 1])
{
strcpy(str, s);
}
~MyString()
{
delete[] str;
}
MyString(const MyString& other) : len(other.len), str(new char[other.len + 1])
{
strcpy(str, other.str);
}
MyString& operator=(const MyString& other)
{
if (this != &other)
{
delete[] str;
len = other.len;
str = new char[len + 1];
strcpy(str, other.str);
}
return *this;
}
MyString& operator=(MyString&& other) noexcept
{
if (this != &other)
{
delete[] str;
str = other.str;
len = other.len;
other.str = nullptr;
other.len = 0;
}
return *this;
}
const char* c_str() const
{
return str;
}
size_t length() const
{
return len;
}
};
int main()
{
MyString s1("abcde");
MyString s2("12345");
s2 = std::move(s1);
cout << "s2: " << s2.c_str() << endl;
cout << "s2 length: " << s2.length() << endl;
cout << "s1 length: " << s1.length() << endl;
return 0;
}
Результат выполнения кода:
"s2: abcde"
"s2 length: 5"
"s1 length: 0"
Смотрите также
-
оператор
копирующего присваивания,
который копирует ресурсы из одного объекта в другой -
конструктор
перемещения,
который перемещает ресурсы при создании объекта -
конструктор
копирования,
который копирует ресурсы при создании объекта -
деструктор
класса,
который освобождает ресурсы при уничтожении объекта