2016-08-12 1 views
2
#include<vector>  
struct A { int a[100]; }; 

void foo (const A& a) { 
    std::vector<A> vA; 
    vA.push_back(std::move(a)); // how does move really happen? 
} 

int main() { 
    A a; 
    foo(a); 
} 

Приведенный выше код компилируется в порядке. Теперь везде написано, что move позволяет избежать копирования.
Ниже приведены мои запросы:Does std :: перемещение работы с ссылками lvalue? Как std :: перемещение работы на стандартных контейнерах?

  1. ли move действительно работают, когда один имеет дело с Lvalue [не] - const ссылки?
  2. Даже с «ссылкой на rvalue», как избежать копирования, когда объект вставлен в стандартный контейнер, как указано выше?

, например.

void foo (A&& a) { // suppose we invoke this version 
    std::vector<A> vA; 
    vA.push_back(std::move(a)); // how copy is avoided? 
} 
+0

Он работает в том смысле, что 'std :: move (a)' создает 'const A &&' (помните, что 'std :: move' просто передает свой аргумент в ссылку rvalue). Но нет такой вещи, как 'push_back (const A &&)' - только 'push_back (const A &)' и 'push_back (A &&)' -, и первая будет вызвана, в результате чего произойдет копия (так как вы не можете привязать константу rvalue ref к не-const rvalue ref, но вы можете привязать ее к ссылке const lvalue). – peppe

+0

Что значит «как избежать копирования?». Вы спрашиваете, как реализуется «вектор :: push_back (T &&)»? –

+0

@SteveJessop, в некотором смысле Да. Но я бы не стал подробно останавливаться на этом. Мой основной вопрос заключается в том, что, поскольку «A && a», исходящий извне, может быть создан в определенном месте. 'std :: vector' - непрерывный контейнер. Как можно вообще избежать копирования? – iammilind

ответ

8

std::move не делает ход. На самом деле он ссылается на ссылку lvalue на ссылку rvalue. В этом случае результатом перемещения является const A && (что, кстати, совершенно бесполезно).

std::vector имеет перегрузку для const A & и A &&, поэтому перегрузка с const A & будет получить выбран и const A && неявно приведен к const A &

Тот факт, что std::move можно назвать на константные объекты, странно/неожиданным поведение для большинства программистов, хотя это как-то разрешено. (Скорее всего, у них был прецедент или нет, чтобы предотвратить это)

Более конкретный для вашего примера будет вызываться конструктор перемещения класса A. Поскольку A является POD, это скорее всего будет делать копию, так как все биты просто должны перемещаться/копироваться в новый экземпляр A.

Поскольку стандарт указывает только, что исходный объект должен быть действительным, хотя неопределенное состояние, ваш компилятор может хранить биты в A на месте и не должен сводить их все к 0. На самом деле большинство компиляторов будут хранить эти биты на месте, так как их изменение требует дополнительных инструкций, что плохо для производительности.

+0

Почему это странно? Тот факт, что 'const T &' может связываться с rvalues, не является новым в C++ 11. – hvd

+0

Позвольте мне уточнить это предложение, я имел в виду существование 'const A &&' – JVApen

+2

Это перестает быть странным, если вы считаете это в C++, добавляя 'std :: move' в бит кода, который иначе привел бы к копированию, и в целом Подвижная концепция означает «переместить, если возможно, в противном случае скопировать». Они не означают «переместить, если это возможно, иначе не скомпилировать». –

 Смежные вопросы

  • Нет связанных вопросов^_^