Смежные контейнеры для хранения и перемещения семантики

Как контейнер может быть одновременно смежным и поддерживать семантику перемещения одновременно?

Пример с 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&& тип, который сам по себе не гарантирует, что вы перемещаете семантику.

Другие вопросы по тегам