Смежные контейнеры для хранения и перемещения семантики
Как контейнер может быть одновременно смежным и поддерживать семантику перемещения одновременно?
Пример с std:: vector: Когда вызывается push_back() с использованием std:: move для lvalue:
std::vector<MyClass> v;
MyClass obj;
MyClass obj2;
vt.push_back(std::move(obj));
vt.push_back(std::move(obj2));
obj и obj2 не обязательно размещаются рядом друг с другом в памяти. Теперь, когда вектор должен иметь свои элементы в смежной памяти, как будет работать семантика перемещения в этом случае? Мне кажется, что он должен скопировать obj2 в непрерывную область памяти вектора v (рядом с obj), иначе требование смежности не будет выполнено. Но для этого нужна копия, а не ход. В чем разница между вышеизложенным и этим тогда?
MyClass obj;
MyClass obj2;
vt.push_back(std::move(obj));
vt.push_back(obj2);
2 ответа
Вам просто нужно прочитать немного больше о семантике перемещения:-)
Перемещение объекта не меняет адрес самого объекта. Он просто вызывает конструктор перемещения (или оператор присваивания и т. Д. В зависимости от контекста) другого экземпляра объекта, которому передается тот, который должен быть перемещен.
В этом примере вектор создает два MyClass
объекты внутри его внутреннего хранилища, один на push_back
, Но для первого, вместо вызова конструктора копирования и передачи obj
(с помощью MyClass const&
), он вызывает конструктор перемещения и передает ссылку на rvalue (MyClass&&
) чтобы obj
, Затем этот конструктор должен переместить содержимое obj
объект в один внутри вектора.
Другими словами, сами объекты создаются в векторе, и только их содержимое перемещается (то, что означает "перемещать" объект, потенциально различно для каждого типа, следовательно, задача конструктора перемещения - выполнять фактическое перемещение).).
Обратите внимание, что даже с std::move
конструктор перемещения не может быть вызван - например, его может не быть, или может не быть noexcept
(в таком случае std::vector
не может использовать его при любых обстоятельствах, не нарушая его исключительные гарантии безопасности).
Ваш std::move
это приведение, это безусловное приведение, и оно может легко распасться в копии, если вы не используете его с правильной семантикой.
Другими словами, написание std::move
не гарантирует вам ничего, кроме T&&
тип, который сам по себе не гарантирует, что вы перемещаете семантику.