Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Benefit from initializer list and in-place construction

Tags:

c++

When having a POD struct:

struct A {
 int a;
 int b;
};

One can do:

std:vector<A> vec;
vec.push_back(A{ .a = 4, .b = 2 });

But I think this ends up making a copy. Using emplace_back will still make a copy. To construct in-place a constructor will need to be added for A like:

A(int a, int b)
: a(a)
, b(b)
{}

and then do

vec.emplace_back(4, 2);

but adding that will forfeit the initializer list usage.

Is there a way to have both? Better yet is there a way to use the initializer list while constructing in place?

A solution would be

vec.emplace_back();
vec.back().a = 4;
vec.back().b = 2;

but this is not what I'm after.

P.S.: I may be wildly wrong in when a copy is taking place or not please correct me as needed.

like image 344
Evangelos Bempelis Avatar asked Sep 14 '25 12:09

Evangelos Bempelis


2 Answers

If you are using C++20 or later, using emplace_back works directly with the values to construct A from, without adding a constructor to A:

#include <vector>
#include <iostream>

struct A {
    int a;
    int b;
};

int main() {
    std::vector<A> vec;
    vec.emplace_back(4, 2);
    std::cout << vec[0].a << ", " << vec[0].b << "\n";
}

Output:

4, 2

Live demo - Godbolt

like image 76
wohlstad Avatar answered Sep 17 '25 03:09

wohlstad


vec.push_back(A{ .a = 4, .b = 2 });

In this case, void push_back( T&& value ); will be called (assuming C++11 at least) with a reference rvalue, so A will be moved, and no copy.

vec.emplace_back(4, 2);

Still no copy, object is constructed in place (C++17) as described here : https://en.cppreference.com/w/cpp/container/vector/emplace_back

like image 38
Fryz Avatar answered Sep 17 '25 03:09

Fryz