It's much faster than using the initializer lists. Here's the result
from a micro benchmark I ran:
2021-01-25T23:49:20+01:00
Running ./bench.g++
Run on (8 X 4500 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x4)
L1 Instruction 32 KiB (x4)
L2 Unified 256 KiB (x4)
L3 Unified 8192 KiB (x1)
Load Average: 1.08, 0.72, 0.60
-------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------
BM_InitializerList 59667 ns 59625 ns 70526
BM_EmplaceBack 24515 ns 24497 ns 176817
BM_EmplaceBack2 16970 ns 16961 ns 247652
BM_PushBack 52831 ns 52796 ns 79202
BM_PushBack2 52858 ns 52823 ns 79004
The five benchmarks were:
• BM_InitializerList — the old way with initializer lists. Basically
the same code currently being replaced.
• BM_EmplaceBack — Reserving space & adding each entry with
g_languages.emplace_back(). A constructor was added to language_t
struct taking the std::strings as const references (std::string
const &), assigning them to the member variables normally.
• BM_EmplaceBack2 — Reserving space & adding each entry with
g_languages.emplace_back(). A constructor was added to language_t
struct taking the std::strings as rvalue references (std::string &&)
assigning them to the member variables using std::move().
• BM_PushBack — Reserving space & adding each entry with
g_languages.push_back(). A constructor was added to language_t
struct taking the std::strings as const references (std::string
const &), assigning them to the member variables normally.
• BM_PushBack2 — Reserving space & adding each entry with
g_languages.push_back(). A constructor was added to language_t
struct taking the std::strings as rvalue references (std::string &&)
assigning them to the member variables using std::move().