Эффективность 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 для уже построенных элементов.