Рух залишити об'єкт у придатному для використання стані?

Скажімо, у мене є два вектори, і я переміщую один до іншого, v1 = std :: move (v2) ; буде v2 все-таки перебувати в доступному стані після цього?

14
Це виглядає як дублікат stackoverflow.com/q/7027523/576911 . Подивіться цю відповідь: stackoverflow.com/questions/7027523/… до цього питання, де обговорюються дозволені операції з точки зору попередніх умов.
додано Автор Howard Hinnant, джерело

3 Відповіді

З n3290, 17.6.5.15 Переміщено з стану бібліотечних типів [lib.types.movedfrom]

  1. Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

Оскільки держава є дійсною, це означає, що ви можете безпечно працювати на v2 (наприклад, присвоїти йому, що поверне його до відомого стану). Оскільки воно не вказане, це означає, що ви не можете, наприклад, спиратися на якесь особливе значення для v2.empty() , якщо воно перебуває в цьому стані (але називаючи його, це не призведе до аварійної роботи програми).

Зауважте, що ця аксіома семантики переміщення ("Переміщення з об'єктів залишилося в дійсному, але невизначеному стані") - це те, що весь код повинен прагнути (більшу частину часу), а не тільки компоненти Стандартної бібліотеки. Схоже, семантика конструкторів копій повинна робити копію, але не застосовується до.

22
додано
+1, але як написано, вам здається, що ви не знаєте, чи v2 порожній після того, як v2 = std :: vector {};
додано Автор Gabriel, джерело
@Gabriel Хороша точка, редагування в порядку.
додано Автор Luc Danton, джерело
7
додано
Це повинно бути дійсним. Інакше що станеться, коли об'єкт вийде з сфери застосування. Швидше за все, в його храмі не буде нічого, але все, що воно є, воно буде дійсним.
додано Автор Damon, джерело
Він залишається у невизначеному але дійсному стані. Тобто, ви все ще можете використовувати об'єкт таким способом, що тільки має передумову дійсності об'єкта. Наприклад, ви можете викликати вектор :: clear() на той переміщений-з вектора, щоб отримати його у відомому стані, а потім почати вставляти в нього об'єкти.
додано Автор bames53, джерело
Існує декілька (абстрактних) рівнів дійсності. Що стосується мови, то об'єкт після переміщення дійсний, оскільки об'єкт все ще існує, його деструктор можна викликати, не викликаючи невизначеної поведінки тощо. Проте договір об'єкта може бути змінений через переміщення . Наприклад, той факт, що вектор став нульовим (не має ємності), є дійсним вектором C ++, але об'єктом, що має метод, який встановлює певний елемент на вектор, не перевіряючи припущення про те, що вектор повинен мати певний розмір, стає ...
додано Автор rwong, джерело
... стає неприйнятною операцією (викличе UB). Такі дані повинні бути документально підтверджені виконавцем об'єкта. Реалізатор також повинен надати документований спосіб відновити зручність використання об'єкта, якщо це буде потрібно.
додано Автор rwong, джерело

Якщо ви хочете використовувати v2 після переміщення, ви хочете зробити щось подібне:

v1 = std::move(v2);
v2.clear();

На цьому етапі v1 буде мати оригінальний вміст v2, і v2 буде в чітко визначеному порожньому стані. Це працює на всіх контейнерах STL (і в рядках для цього), і якщо ви реалізуєте свої власні класи, які підтримують семантику переміщення, ви, мабуть, захочете зробити щось подібне.

Якщо ваша особлива реалізація STL фактично залишає об'єкт у порожньому стані, то другий clear() буде по суті без оп. Насправді, якщо це так, це буде правова оптимізація для компілятора для усунення clear() після переміщення.

0
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147