Эффективность C++11 push back () с std:: move против emplace back () для уже построенных объектов
В C++11 emplace_back()
обычно предпочтительнее (с точки зрения эффективности)push_back()
как это позволяет на месте строительства, но это все еще имеет место при использовании push_back(std::move())
С уже построенным объектом?
например,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, он вызывает Move-конструкторstd::string
, т. е. это конструкция перемещения на месте, как в 2.другими словами, если вызывается с одним аргументом типа T, будь то rvalue или lvalue,
emplace_back
иpush_back
эквивалентны.однако, для любого другого аргумента(ов),
emplace_back
выигрывает гонка, например сchar const*
наvector<string>
:
emplace_back("foo")
звонкиstring::string(char const*)
на месте строительства.
push_back("foo")
сразуstring::string(char const*)
для неявного преобразования, необходимого для соответствия сигнатуре функции, а затем для вставки перемещения, как в случае 2. выше. Поэтому он эквивалентенpush_back(string("foo"))
emplace_back получает список ссылок rvalue и пытается построить элемент контейнера непосредственно на месте. Вы можете вызвать emplace_back со всеми типами, которые поддерживают конструкторы элементов контейнера. При вызове emplace_back для параметров, которые не являются ссылками rvalue, он "возвращается" к обычным ссылкам и, по крайней мере, конструктор копирования вызывается, когда параметр и элементы контейнера имеют один и тот же тип. В твоем случае, мой вектор.emplace_back( mystring) ' должен сделать копию строки, потому что компилятор не может знать, что параметр myvector является подвижным. Поэтому вставьте std:: переместить то, что дает вам желаемую выгоду. В push_back должен работать так же, как emplace_back для уже построенных элементов.