Почему emplace_back быстрее push_back?

я думал так emplace_back был бы победителем, когда делал что-то вроде этого:

v.push_back(myClass(arg1, arg2));

так как emplace_back построит объект сразу в векторе, в то время как push_back, сначала создаст анонимный объект, а затем скопирует его в вектор. Для получения дополнительной информации см. этот вопрос.

Google также дает этот а также этот вопросы.

Я решил сравнить их для вектора, который будет заполнен целыми числами.

Вот код эксперимента:

#include <iostream>
#include <vector>
#include <ctime>
#include <ratio>
#include <chrono>

using namespace std;
using namespace std::chrono;

int main() {

vector<int> v1;

const size_t N = 100000000;

high_resolution_clock::time_point t1 = high_resolution_clock::now();
for(size_t i = 0; i < N; ++i)
v1.push_back(i);
high_resolution_clock::time_point t2 = high_resolution_clock::now();

duration<double> time_span = duration_cast<duration<double>>(t2 - t1);

std::cout << "push_back took me " << time_span.count() << " seconds.";
std::cout << std::endl;

vector<int> v2;

t1 = high_resolution_clock::now();
for(size_t i = 0; i < N; ++i)
v2.emplace_back(i);
t2 = high_resolution_clock::now();
time_span = duration_cast<duration<double>>(t2 - t1);
std::cout << "emplace_back took me " << time_span.count() << " seconds.";
std::cout << std::endl;

return 0;
}

Результатом является то, что emplace_back быстрее.

push_back took me 2.76127 seconds.
emplace_back took me 1.99151 seconds.

Зачем? Ответ на 1-й связанный вопрос ясно говорит о том, что не будет никакой разницы в производительности.

Также пробовал с другими методы времени с моего псевдо-сайта, но идентичные результаты.

[РЕДАКТИРОВАТЬ] Комментарии говорят, что тестирование с ints ничего не говорит и что push_back принимает реф.

Я сделал тот же тест в коде выше, но вместо int У меня был класс A:

class A {
public:
A(int a) : a(a) {}
private:
int a;
};

Результат:

push_back took me 6.92313 seconds.
emplace_back took me 6.1815 seconds.
[EDIT.2]

Как сказал Денлан, я должен также изменить положение операций, поэтому я поменял их местами и в обеих ситуациях (int а также class A), emplace_back снова был победителем.

[РЕШЕНИЕ]

Я запускал код в debug mode, что делает измерения недействительными. Для бенчмаркинга всегда запускайте код в release mode,

27

Решение

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

Вот лучшее сравнение:

Foo x; Bar y; Zip z;

v.push_back(T(x, y, z));  // make temporary, push it back
v.emplace_back(x, y, z);  // no temporary, directly construct T(x, y, z) in place

Ключевое отличие, однако, заключается в том, что emplace_back выполняет явный преобразования:

std::vector<std::unique_ptr<Foo>> v;
v.emplace_back(new Foo(1, 'x', true));  // constructor is explicit!

Этот пример будет слегка надуманным в будущем, когда вы должны сказать v.push_back(std::make_unique<Foo>(1, 'x', true)), Тем не менее, другие конструкции очень хороши с emplace, тоже:

std::vector<std::thread> threads;
threads.emplace_back(do_work, 10, "foo");    // call do_work(10, "foo")
threads.emplace_back(&Foo::g, x, 20, false);  // call x.g(20, false)
40

Другие решения


По вопросам рекламы [email protected]