C++: push() стека против emplace()
Пытаясь понять разницу между использованием push()
или же emplace()
за std::stack
,
Я думал, что если я создам std::stack<int>
тогда я бы использовал push()
потому что целое число является примитивным типом, и нет ничего для emplace()
строить.
Тем не менее, если бы я создавал std::stack<string>
тогда я бы выбрал emplace()
так как std::string
это объект.
Это правильное использование?
2 ответа
Чтобы полностью понять, что делает emplace_back, нужно сначала понять шаблоны переменных и ссылки на значения.
Это довольно продвинутая и глубокая концепция в современном C++. На карте это будет помечено как "там будут драконы".
Вы говорите, что вы новичок в C++ и пытаетесь изучить этот материал. Возможно, это не тот ответ, который вы искали, но вы должны пропустить эту деталь на данный момент и вернуться позже, после того как вы обернули свой мозг вокруг вариационных шаблонов и ссылок на rvalue. Тогда все должно иметь смысл.
Но если вы настаиваете: для контейнера, содержащего простые элементарные типы, такие как целые числа, разницы мало, если вообще есть. Разница возникает, когда тип контейнера - это какой-то большой, сложный класс со сложным конструктором и / или конструктором копирования.
Конечный результат либо push, либо emplace в точности равен 100%. К контейнеру добавляется еще один элемент. Разница в том, откуда этот элемент:
1) push принимает существующий элемент и добавляет его копию в контейнер. Просто, понятно. push всегда принимает ровно один аргумент, элемент для копирования в контейнер.
2) emplace создает другой экземпляр класса в контейнере, который уже добавлен в контейнер. Аргументы для emplace передаются в качестве аргументов конструктору класса контейнера. Emplace может иметь один аргумент, более одного аргумента или вообще не иметь аргумента, если класс имеет конструктор по умолчанию.
Обратите внимание, что когда конструктор класса принимает один аргумент, и он не помечается как explicit
можно использовать push и передать ему аргумент конструктора вместо существующего экземпляра класса. Но давайте представим, что эта опция не существует, она часто приводит к ужасной производительности кода, особенно с нетривиальными классами.
Итак: если вы хотите добавить копию существующего экземпляра класса в контейнер, используйте push. Если вы хотите создать новый экземпляр класса с нуля, используйте emplace.
Если у тебя есть vector<X>
, затем emplace_back(a, b, c)
конструирует X
объект внутри вектора.
В отличие от push_back(X(a, b, c))
сначала создается временный объект, который затем перемещается в вектор.