При перемещении unordered_set
на GCC 4.9, а затем повторно используя перемещенный объект, я получаю деление на ноль, когда добавляю к нему.
Мое понимание (от http://en.cppreference.com/w/cpp/utility/move) заключается в том, что перемещенный объект может использоваться при условии, что ни одно из его предварительных условий не нарушено. призвание clear()
с перемещенным набором все в порядке (что имеет смысл в контексте предварительных условий), но мне не ясно, что я нарушаю любое предварительное условие, добавляя новый элемент.
Пример кода:
#include <unordered_set>
using namespace std;
void foo(unordered_set<int> &&a) {
unordered_set<int> copy = std::move(a);
}
void test() {
unordered_set<int> a;
for (int i = 0; i < 12; ++i) a.insert(i);
foo(std::move(a));
a.clear();
a.insert(34); // divide by zero here
}
int main() {
test();
}
Этот код прекрасно работает на GCC4.7 — это проблема в GCC4.9? unordered_set
реализация или, как я понимаю, что значит нарушать предварительные условия для перемещенных объектов?
Это PR 61143. Это было исправлено для gcc-4.10, и исправление было перенесено вовремя для 4.9.1.
Марк Глисс уже направил вас к ошибке GCC, но чтобы ответить на ваш вопрос:
это проблема … в моем понимании того, что значит нарушать предварительные условия для перемещенных объектов?
Нет, это не так, ваше понимание верно. Работа с кодом в вашем вопросе — это не просто расширение GCC, ваша программа отлично работает. Предполагается, что перемещенный объект типа, определенного в стандартной библиотеке, останется пригодным для использования. Вы ничего не знаете о его состоянии, но, например, любой контейнер является пустым или не пустым, поэтому перемещенный контейнер также является пустым или не пустым. Что из этого не определено, но ваша программа может проверить, и реализация стандартной библиотеки должна вести себя так, как нужно для результата проверки вашей программы.