Можно ли вызвать `emplace_back()` без параметров у `std::vector`?

«Можно ли вызвать `emplace_back()` без параметров у `std::vector`?» — вопрос из категории STL, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, можно, но только если тип элемента вектора (T) имеет конструктор по умолчанию.

Вызов vec.emplace_back(); эквивалентен созданию элемента с помощью T() и его размещению в конце вектора. Это работает благодаря perfect forwarding и вызову конструктора T с пустым списком аргументов.

Пример:

#include <vector>
#include <string>

int main() {
    std::vector<std::string> words;
    words.emplace_back(); // Создает пустую строку, вызывая std::string().
    // words теперь содержит: [""]

    std::vector<int> numbers;
    numbers.emplace_back(); // Создает int, инициализированный нулем (int()).
    // numbers теперь содержит: [0]
}

Что произойдет, если конструктора по умолчанию нет? Компиляция завершится ошибкой.

struct Point {
    int x, y;
    Point(int x, int y) : x(x), y(y) {} // Пользовательский конструктор
    // Конструктор по умолчанию Point() = default; не сгенерирован
};

std::vector<Point> points;
points.emplace_back(); // ОШИБКА КОМПИЛЯЦИИ:
// Нет подходящего конструктора для вызова 'Point::Point()'

Сравнение с push_back:

vec.push_back(T()); // Требует создания временного объекта, затем его перемещения/копирования.
vec.emplace_back(); // Создает объект напрямую в памяти вектора, избегая лишних операций.

Вывод: emplace_back() без аргументов — это эффективный способ добавить в вектор элемент, инициализированный значением по умолчанию, при условии, что такой конструктор существует.