отодвинуть против установки обратно
Я немного запутался относительно разницы между push_back и emplace_back.
void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);
как есть push_back перегрузка принимая ссылку rvalue я не совсем понимаю, что цель emplace_back будет?
6 ответов:
в дополнение к тому, что посетитель сказал :
функции
void emplace_back(Type&& _Val)предоставленный MSCV10 не соответствует и избыточен, потому что, как вы отметили, он строго эквивалентенpush_back(Type&& _Val).но реальная C++0x форма
emplace_back- это действительно полезно:void emplace_back(Args&&...);вместо
value_typeон принимает вариативный список аргументов, так что это означает, что теперь вы можете прекрасно переслать Аргументы и построить непосредственно объект в a контейнер без временного вообще.это полезно, потому что независимо от того, сколько ума RVO и Move semantic приносят в таблицу, все еще есть сложные случаи, когда push_back, вероятно, сделает ненужные копии (или переместит). Например, с традиционным
emplace_backне следует принимать аргумент типаvector::value_type, но вместо этого переменные аргументы, которые передаются в конструктор добавленного элемента.template <class... Args> void emplace_back(Args&&... args);можно пройти a
value_typeкоторый будет перенаправлен в конструктор копирования.поскольку он пересылает аргументы, это означает, что если у вас нет rvalue, это все равно означает, что контейнер будет хранить "скопированную" копию, а не перемещенную копию.
std::vector<std::string> vec; vec.emplace_back(std::string("Hello")); // moves std::string s; vec.emplace_back(s); //copiesно выше должно быть идентично тому, что
push_backделает. Вероятно, это скорее предназначено для таких случаев использования, как:std::vector<std::pair<std::string, std::string> > vec; vec.emplace_back(std::string("Hello"), std::string("world")); // should end up invoking this constructor: //template<class U, class V> pair(U&& x, V&& y); //without making any copies of the strings
оптимизация
emplace_backможно продемонстрировать в следующем примере.на
emplace_backконструкторA (int x_arg)будет называться. Иpush_backA (int x_arg)называется первым иmove A (A &&rhs)называется потом.конечно, конструктор должен быть помечен как
explicit, но для текущего примера хорошо удалить явность.#include <iostream> #include <vector> class A { public: A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; } A () { x = 0; std::cout << "A ()\n"; } A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; } A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; } private: int x; }; int main () { { std::vector<A> a; std::cout << "call emplace_back:\n"; a.emplace_back (0); } { std::vector<A> a; std::cout << "call push_back:\n"; a.push_back (1); } return 0; }выход:
call emplace_back: A (x_arg) call push_back: A (x_arg) A (A &&)
emplace_backсоответствующая реализация будет пересылать аргументы вvector<Object>::value_typeконструктор при добавлении в вектор. Я помню, что Visual Studio не поддерживала вариативные шаблоны, но с вариативными шаблонами будет поддерживаться в Visual Studio 2013 RC, поэтому я думаю, что будет добавлена соответствующая подпись.С
emplace_back, Если вы переадресуете аргументы непосредственно вvector<Object>::value_typeконструктор, вам не нужно, чтобы тип был подвижным или копируемым дляemplace_backфункция, строго говоря. Вvector<NonCopyableNonMovableObject>случае, это не полезно, Так какvector<Object>::value_typeтребуется копируемый или подвижный тип для роста.но Примечание что это может быть полезно для
std::map<Key, NonCopyableNonMovableObject>, так как как только вы выделяете запись на карте, ее больше не нужно перемещать или копировать, в отличие отvector, это означает, что вы можете использоватьstd::mapэффективно с отображенным типом, который не является ни копируемым, ни подвижным.
еще один в списках:
/ / создает элементы на месте.
emplace_back("элемент");//он создаст новый объект, а затем скопировать(или переместить) его значение аргументов. push_back (explicitDataType {"element"});
хороший код для push_back и emplace_back показан здесь.
http://en.cppreference.com/w/cpp/container/vector/emplace_back
вы можете увидеть операцию перемещения на push_back, а не на emplace_back.
Comments