C++ - std::piecewise_constructor to avoid temporary object creation

1 minute read

Streamlining C++ Code - Avoiding Unnecessary C++ Object Creation - C++Now 2025

This constructs both elements in place, preventing unnecessary temporaries.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <map>
#include <tuple>
#include <string>

struct Key {
    std::string name;
    int id;

    Key(std::string n, int i) : name(std::move(n)), id(i) {
        std::cout << "Key constructed\n";
    }
};

struct Value {
    double score;
    int level;

    Value(double s, int l) : score(s), level(l) {
        std::cout << "Value constructed\n";
    }
};

int main() {
    std::map<Key, Value> m;

    m.emplace(
        std::piecewise_construct,
        std::forward_as_tuple("Alice", 1),      // Key constructor args
        std::forward_as_tuple(98.5, 3)          // Value constructor args
    );

    std::cout << "Map size = " << m.size() << "\n";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <tuple>
#include <utility>
#include <string>

struct A {
    A(int x, int y) { 
        std::cout << "A(" << x << ", " << y << ")\n"; 
    }
};

struct B {
    B(std::string s) { 
        std::cout << "B(" << s << ")\n"; 
    }
};

int main() {
    std::pair<A, B> p(
        std::piecewise_construct,
        std::forward_as_tuple(10, 20),      // Arguments for A
        std::forward_as_tuple("hello")      // Arguments for B
    );
}

Optional example to avoid the temporal object creation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <optional>
#include <string>

struct Person {
    std::string name;
    int age;

    Person(std::string n, int a) : name(std::move(n)), age(a) {
        std::cout << "Person constructed\n";
    }
};

int main() {
    // Create an optional<Person> with constructor arguments
    std::optional<Person> p = std::make_optional<Person>("Alice", 30);

    std::cout << p->name << ", " << p->age << "\n";

    std::optional<Data> opt(std::in_place, "test", 20);
    std::cout << opt->name << ", " << opt->age << "\n";
}

Categories:

Updated: