отодвинуть против установки обратно



Я немного запутался относительно разницы между 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 будет?

672   6  

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

    Ничего не найдено.