`[] (Std :: list <int>& list) {return std :: move (list)} (list)` гарантированно оставит `list` пустым? - PullRequest
1 голос
/ 11 февраля 2020

Более конкретно:

struct A{
    std::list<int> list;
    std::list<int> foo(){
        return std::move(list);
    }
}

A a;
// insert some elements into a.list
a.foo(); // is this guaranteed to clear a.list?

Гарантируется, что последняя строка выше оставит a.list пустой?

Ответы [ 4 ]

3 голосов
/ 11 февраля 2020

Нет. Переход от большинства стандартных библиотечных классов оставляет их в «допустимом, но неопределенном состоянии» [1]. Это означает, что вы должны явно очистить a.list, чтобы убедиться, что он пуст после перемещения.

[1] Из этого правила есть исключения: прежде всего, std::unique_ptr должен быть нулевым после двигаться.

1 голос
/ 11 февраля 2020

В последней строке выше гарантированно оставлен a.list пустым?

Нет. Стандарт гласит следующее:

[lib.types.movedfrom]

Объекты типов, определенных в стандартной библиотеке C ++, могут быть перемещены из ([class.copy.ctor]). Операции перемещения могут быть явно указаны или неявно сгенерированы. Если не указано иное, такие перемещенные объекты должны быть помещены в допустимое, но неопределенное состояние.

И это определение допустимое, но неопределенное состояние :

[defns.valid]

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

[Пример: Если объект x типа std :: vector находится в допустимом, но неопределенном состоянии, x.empty () может быть вызван безоговорочно, а x.front () может быть вызван, только если x.empty () возвращает false. - конец примера]

std::list спецификация не добавляет никаких дополнительных гарантий для конструктора перемещения.

0 голосов
/ 12 февраля 2020

Возможно, стоит объяснить, почему список может впоследствии не быть пустым.

Если перемещение заканчивается копией, например, из-за несовместимых распределителей, и распределитель не перемещается, тогда список все еще может иметь старые элементы.

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

0 голосов
/ 11 февраля 2020

Нет, вы должны очистить его, иначе он останется в «неопределенном состоянии» - согласно документации на std::list

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