Undefined поведение с std:: move

Из переместить страницу cppreference

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

Итак, из примера на той же странице, этот код ниже считается undefined поведение

vector<string> v_string;
string example = "example";
v_string.push_back(move(example));
cout << example << endl;
</string>

MSVC ничего не выведет на консоль, но если я сделаю это

vector<int> v_int;
int number = 10;
v_int.push_back(move(number));
cout << number << endl;
</int>

выйдет 10. Есть ли причина, почему это происходит? Или это всегда undefined поведение?

3 ответа

Unspecified не означает undefined.

Согласно стандарту С++ 11, раздел 17.3.26:

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

Поскольку объект находится в допустимом состоянии, вы можете передать его на выход, поскольку потоковая передача не имеет дополнительных предварительных условий. Однако то, что напечатано, не указано, поэтому оно может просто ничего не напечатать или не напечатать, что ваш отец пахнет бузиной. То, что вы не можете смело сделать, это использовать функцию с дополнительными предварительными условиями, такими как back(), которая дополнительно требует, чтобы строка была непустой. Действительные строки могут быть пустыми.

Содержащее старое значение является вполне приемлемым вариантом для неуказанного, но действительного состояния. В случае фундаментальных типов, таких как int, простая копия является всего лишь самым эффективным способом выполнения перемещения.

Следует также отметить, что int не является стандартным объектом библиотеки, а является фундаментальным типом (как определено в разделе 3.9.1). Поэтому ваша цитата не применяется.


Это связано с тем, что string может эффективно move d из-за кражи указателя, указывающего на фактические символы, так что то, что делают компиляторы, оставляя move d из string "пустым". int не может быть эффективно move d, вы просто делаете копию. Поэтому старый int все еще существует. Но это не так. Просто не используйте объекты, которые вы move ed, и не полагайтесь на неуказанное поведение.


Undefined поведение просто означает

для которого настоящий международный стандарт не предъявляет никаких требований. Допустимое поведение undefined варьируется от игнорирования ситуации полностью с непредсказуемыми результатами, вести себя во время перевода или выполнения программы документированным образом, характерным для (с выдачей диагностического сообщения или без него), чтобы прекращение перевода или исполнения (с выдачей диагностическое сообщение). Многие ошибочные программные конструкции не порождают undefined поведение; они должны быть диагностированы.

Если вам интересно, посмотрите Что должен знать каждый программист C о поведении undefined. Это действительно открывающий глаза.

В вашем случае это не поведение undefined, но неуказанное состояние: В 21.4.2.16 стандарт С++ определяет семантику конструктора перемещения:

Создает объект класса basic_string, как указано в таблице 69. Сохраненный распределитель построен из alloc. Во второй форме str остается в допустимом состоянии с неопределенным значением.

"Вторая форма" - это конструктор перемещения, поэтому строка находится в неопределенном состоянии.

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

licensed under cc by-sa 3.0 with attribution.