Эта стоимость сводится к векторному обнулению памяти через ее распределитель.
Во-первых, всегда полезно использовать библиотеку сравнения, такую как Google Benchmark , а не скользящую.ваш собственный бенчмаркинг.Мы можем использовать quick-bench.com , чтобы быстро использовать библиотеку.Перепишите код, чтобы использовать это:
// Just the benchmark code:
void getVector1(benchmark::State& state)
{
int n = state.range(0);
for (auto _ : state) {
std::vector<int> ivec(n);
// This is the same operation that you are doing
std::iota(ivec.begin(), ivec.end(), 1);
// We don't want the compiler to see that we aren't
// using `ivec` and thus optimize away the entire
// loop body
benchmark::DoNotOptimize(ivec);
}
}
void getArray1(benchmark::State& state)
{
int n = state.range(0);
for (auto _ : state) {
auto pvec = new int[n];
std::iota(pvec, pvec + n, 1);
benchmark::DoNotOptimize(pvec);
delete[] pvec;
}
}
// Smaller number still reproduces it
BENCHMARK(getVector1)->Arg(10000);
BENCHMARK(getArray1)->Arg(10000);
Нажмите на изображение для ссылки быстрого стенда
Путем небольшой игры мы можем обнаружить, что разница в стоимости - это просто стоимость обнуления памяти с помощью std::uninitialized_fill
( на быстром бенче ).
Действительно, если вместо этого мы используем распределитель, который оставляет неинициализированной память , то между этими двумя значениями нет ощутимой разницы:
// Allocator from https://stackoverflow.com/a/41049640
template <typename T, typename A = std::allocator<T>>
class default_init_allocator : public A {
typedef std::allocator_traits<A> a_t;
public:
// http://en.cppreference.com/w/cpp/language/using_declaration
using A::A; // Inherit constructors from A
template <typename U> struct rebind {
using other =
default_init_allocator
< U, typename a_t::template rebind_alloc<U> >;
};
template <typename U>
void construct(U* ptr)
noexcept(std::is_nothrow_default_constructible<U>::value) {
::new(static_cast<void*>(ptr)) U;
}
template <typename U, typename...Args>
void construct(U* ptr, Args&&... args) {
a_t::construct(static_cast<A&>(*this),
ptr, std::forward<Args>(args)...);
}
};
void getVector1(benchmark::State& state)
{
int n = state.range(0);
for (auto _ : state) {
std::vector<int, default_init_allocator<int>> ivec(n);
std::iota(ivec.begin(), ivec.end(), 1);
benchmark::DoNotOptimize(ivec);
}
}
void getArray1(benchmark::State& state)
{
int n = state.range(0);
for (auto _ : state) {
auto pvec = new int[n];
std::iota(pvec, pvec + n, 1);
benchmark::DoNotOptimize(pvec);
delete[] pvec;
}
}
BENCHMARK(getVector1)->Arg(10000);
BENCHMARK(getArray1)->Arg(10000);
Нажмите на изображение для быстрой ссылки на стенд