Ответ
В C++ rvalue (правостороннее значение) — это категория выражения, которая обычно обозначает временный, не имеющий имени объект, который нельзя использовать слева от оператора присваивания. Начиная с C++11, введение rvalue-ссылок (&&) стало основой для move-семантики, позволяющей эффективно "перемещать" ресурсы из временных объектов, избегая дорогостоящих глубоких копий.
Ключевые моменты:
- Примеры rvalue: литералы (
42,"hello"), результаты вызовов функций, возвращающих не-ссылку, арифметические выражения (x + 5). - Rvalue-ссылки (
T&&): Ссылаются только на временные объекты (rvalues). Их основное назначение — реализация конструкторов перемещения и операторов присваивания перемещением. - Move-семантика: Позволяет "перехватить" ресурсы (например, динамическую память) из временного объекта, оставив исходный объект в допустимом, но неопределенном состоянии.
Практический пример:
#include <utility> // для std::move
#include <vector>
class MyString {
char* data;
public:
// Конструктор перемещения (принимает rvalue-ссылку)
MyString(MyString&& other) noexcept : data(other.data) {
other.data = nullptr; // "обнуляем" источник, чтобы его деструктор ничего не удалил
}
// Оператор присваивания перемещением
MyString& operator=(MyString&& other) noexcept {
if (this != &other) {
delete[] data; // освобождаем свои старые ресурсы
data = other.data; // забираем ресурсы из `other`
other.data = nullptr;
}
return *this;
}
// ... (конструктор копирования, деструктор и т.д.)
};
int main() {
MyString s1("Hello");
// std::move превращает lvalue `s1` в rvalue, разрешая вызов конструктора перемещения
MyString s2 = std::move(s1); // Ресурсы "переехали" из s1 в s2, копирования не было.
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // Вектор v2 забрал внутренний буфер у v1.
// Теперь v1 пуст (size() == 0, capacity() == 0).
return 0;
}