Ответ
Да, можно, но только если тип элемента вектора (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() без аргументов — это эффективный способ добавить в вектор элемент, инициализированный значением по умолчанию, при условии, что такой конструктор существует.