Почему push_back не может быть перегружен, чтобы выполнить работу emplace_back? - PullRequest
45 голосов
/ 09 августа 2011

Во-первых, я знаю этот вопрос , но я не верю, что задаю то же самое.

Я знаю, что std::vector<T>::emplace_back делает - и я понимаю, почему я использовал бы его вместо push_back(). Он использует шаблоны с переменным числом аргументов, что позволяет мне передавать несколько аргументов в конструктор нового элемента.

Но я не понимаю, почему комитет по стандартам C ++ решил, что существует необходимость в новой функции-члене. Почему они не могли просто расширить функциональность push_back(). Насколько я вижу, push_back может быть перегружен в C ++ 11, чтобы быть:

template <class... Args>
void push_back(Args&&... args);

Это не нарушило бы обратную совместимость, позволяя вам передавать N аргументов, включая аргументы, которые будут вызывать нормальное значение или конструктор копирования. Фактически, реализация GCC C ++ 11 push_back() в любом случае просто вызывает emplace_back:

  void push_back(value_type&& __x)
  { 
    emplace_back(std::move(__x)); 
  }

Итак, как я вижу, нет необходимости в emplace_back(). Все, что им нужно было добавить, это перегрузка для push_back(), которая принимает переменные аргументы и передает аргументы конструктору элемента.

Я здесь не прав? Есть ли какая-то причина, по которой здесь нужна была совершенно новая функция?

Ответы [ 2 ]

41 голосов
/ 09 августа 2011

Если у T есть явный конструктор преобразования, то поведение emplace_back и push_back.

отличается.
struct X
{
    int val;
    X() :val() {}
    explicit X(int v) :val(v) {}
};

int main()
{
    std::vector<X> v;
    v.push_back(123);    // this fails
    v.emplace_back(123); // this is okay
}

Внесение предложенного вами изменения будет означать, что push_back будет допустимым в этом случае, и я полагаю, что это нежелательное поведение. Я не знаю, является ли это причиной, но это единственное, что я могу придумать.

0 голосов
/ 25 июня 2017

Вот еще один пример.

Честно говоря, оба семантически настолько различны, что их похожее поведение следует рассматривать как простое совпадение (из-за того факта, чточто в C ++ есть «конструкторы копирования» с определенным синтаксисом).

Вам действительно не следует использовать emplace_back, если вы не хотите семантика на месте конструкции .
Редко, когда тебе нужна такая вещь.Вообще push_back это то, что вы действительно, семантически хотите.

#include <vector>

struct X { X(struct Y const &); };
struct Y { Y(int const &); operator X(); };

int main()
{
    std::vector<X> v;
    v.   push_back(Y(123));  // Calls Y::operator X() and Y::Y(int const &)
    v.emplace_back(Y(123));  // Calls X::X(Y const &) and Y::Y(int const &)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...