Эффективность C++11 push back() с std:: move против emplace back () для уже построенных объектов
В C++11 emplace_back() обычно предпочтительнее (с точки зрения эффективности)push_back() как это позволяет на месте строительства, но это все еще имеет место при использовании push_back(std::move()) С уже построенным объектом?
например, is emplace_back() по-прежнему предпочтительнее в таких случаях, как следующее?
std::string mystring("hello world");
std::vector<std::string> myvector;
myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)
кроме того, есть ли какая-либо польза в приведенном выше примере, чтобы вместо этого делать:
myvector.emplace_back(std::move(mystring));
или перемещение здесь полностью избыточно, или не имеет эффект?
2 ответов
давайте посмотрим, что различные вызовы, которые вы предоставили делать:
emplace_back(mystring): Это конструкция на месте нового элемента с любым аргументом, который вы предоставили. Поскольку вы предоставили lvalue, эта конструкция на месте фактически является копией-конструкцией, т. е. это то же самое, что и вызовpush_back(mystring)push_back(std::move(mystring)): это вызывает Move-insertion, который в случае std::string ist на месте ход строительства.emplace_back(std::move(mystring)): это снова конструкция на месте с аргументами, которые вы предоставили. Поскольку этот аргумент является rvalue, он вызывает конструктор movestd::string, т. е. это конструкция перемещения на месте, как в 2.
другими словами, если вызывается с одним аргументом типа T, будь то rvalue или lvalue, emplace_back и push_back эквивалентны.
однако, для любого другого аргумента(ов),emplace_back выигрывает гонка, например, с char const* на vector<string>:
emplace_back("foo")звонкиstring::string(char const*)для in-place-конструкции.push_back("foo")сразуstring::string(char const*)для неявного преобразования, необходимого для соответствия сигнатуре функции, а затем вставки перемещения, как в случае 2. выше. Поэтому это эквивалентноpush_back(string("foo"))
emplace_back получает список ссылок rvalue и пытается создать элемент контейнера непосредственно на месте. Вы можете вызвать emplace_back со всеми типами, которые поддерживают конструкторы элементов контейнера. При вызове emplace_back для параметров, которые не являются ссылками rvalue, он "возвращается" к обычным ссылкам и, по крайней мере, конструктор копирования вызывается, когда параметр и элементы контейнера имеют один и тот же тип. В вашем случае 'myvector.emplace_back (mystring) ' должен сделать копию из-за строки компилятор не мог знать, что параметр myvector является подвижным. Поэтому вставьте std:: move, что дает вам желаемое преимущество. В push_back должен работать так же, как emplace_back для уже построенных элементов.