Нужно ли сбрасывать std :: list после перемещения? - PullRequest
0 голосов
/ 08 октября 2018

У меня есть следующий код:

std::list some_data;
...
std::list new_data = std::move(some_data);
some_data.clear();
...

Вопрос в том, нужен ли some_data.clear()?(для записи, some_data будет использоваться повторно в будущем)

Ответы [ 5 ]

0 голосов
/ 08 октября 2018

Краткий ответ:
Да, вы должны очистить его, потому что стандарт явно не определяет, в каком состоянии находится список источников после перемещения.
Кроме того, всегда вызывается clear() когда контейнер повторно используется после перемещения, это простое правило, которое не должно вызывать значительных накладных расходов, даже если оно избыточно.

Более длинный ответ:
Как я уже упоминал в некоторыхкомментарии, я не могу представить никакой законной и разумной реализации, для которой источник std::list будет чем-то иным, кроме пустого std::list после использования в качестве источника для конструктора перемещения (спасибо @Lightness Races в Orbit за копание в стандарте).Построение перемещения должно происходить за линейное время, что не допускает никаких операций для каждого объекта, а AFAIK также не позволяет иметь небольшой буфер фиксированного размера, который может быть источником оставшихся «зомби» элементов всписок источников.

Однако, даже если вы можете отследить все это в стандарте, вам все равно придется документировать это всякий раз, когда вы пропускаете clear() в коде, и опасаться, что кто-то изменит код, заменивstd::list с доморощенным контейнером, который не в полной мере отвечает требованиям стандарта (например, для использования оптимизации небольшого буфера).Кроме того, предыдущий оператор действителен только для хода конструкция .При назначении хода абсолютно возможно, что перемещенный контейнер не будет пустым.

В заключение: даже если технически правильно было не использовать clear в данном конкретном случае, это не стоит психических усилийчтобы сделать это (и если вы находитесь в среде, где это того стоит, вы, вероятно, настраиваете свой код на конкретную версию стандартной библиотеки, а не на стандартный документ в любом случае).

0 голосов
/ 08 октября 2018

Это скорее зависит от того, что вы подразумеваете под «повторным использованием».Существует много повторных использований, которые полностью определяют состояние объекта, независимо от его предыдущего состояния.

Очевидным является присвоение перемещенному объекту, что происходит при наивном обмене

template <typename T>
void swap(T& lhs, T& rhs)
{
    T temp = std::move(lhs);
    lhs = std::move(rhs); // lhs is moved-from, but we don't care.
    rhs = std::move(temp); // rhs is moved-from, but we don't care.
}

Если вместо этого вы хотите «повторно использовать», позвонив по номеру some_data.push_back, тогда да, вам следует clear сначала

0 голосов
/ 08 октября 2018

В рабочем проекте стандарта (N4713) говорится о состоянии объектов после их перемещения из:

20.5.5.15 Состояние перемещенных из библиотеки типов [lib.types.movefrom]
1 Объекты типов, определенных в стандартной библиотеке C ++, могут быть перемещены из.Операции перемещения могут быть явно указаны или неявно сгенерированы. Если не указано иное, такие перемещенные объекты должны быть помещены в действительное, но неопределенное состояние.

20.3.25 [defns.valid]
допустимо, нонеопределенное значение состояния объекта, которое не указано, за исключением того, что соблюдаются инварианты объекта и операции над объектом ведут себя так, как указано для его типа

Единственные операции, которые можно безопасно выполнить с контейнером, перемещенным изэто те, которые не требуют предварительных условий.clear не имеет предварительных условий.И он вернет объект в известное состояние, из которого он может быть использован снова.

0 голосов
/ 08 октября 2018

Нет, это не необходимо , чтобы очистить список.Это просто разумно и удобно.

Список будет иметь N элементов, каждый из которых принимает неопределенное значение, для некоторого N≥0.Поэтому, если вы хотите переназначить список, вы можете теоретически присвоить элементам, которые хранятся, а не очистить, и заново вставить все с нуля.поэтому на практике клиринг - это правильный выбор.

0 голосов
/ 08 октября 2018

Да, это необходимо.

Гарантируется, что только интеллектуальные указатели std будут переведены в состояние по умолчанию после перемещения из.

Контейнеры находятся в допустимом, но неопределенном состоянии.Это означает, что вы можете вызывать только функции-члены без предварительных условий, например, clear, которые переводят объект в полностью известное состояние.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...