C/C++ Arena

Step 4 of 7

Return by value is free

A common worry is that returning a big object from a function is slow, so people return pointers or fill in "out" parameters instead. In modern C++ that worry is outdated.

#include <iostream>
#include <string>

struct Loud {
    std::string tag;
    explicit Loud(std::string t) : tag(t) { std::cout << "construct " << tag << "\n"; }
    Loud(const Loud& o) : tag(o.tag) { std::cout << "COPY " << tag << "\n"; }
};

Loud make_direct() {
    return Loud("direct");           // guaranteed: built right in the caller
}

Loud make_named() {
    Loud l("named");
    l.tag += "!";
    return l;                        // NRVO in practice
}

int main() {
    Loud a = make_direct();
    Loud b = make_named();
    std::cout << a.tag << " " << b.tag << "\n";
    Loud c = a;                      // a real copy, because we asked for one
}
construct direct
construct named
direct named!
COPY direct

Reading the output

What this means for your code

Your task

The Tracker struct counts copies. Write Tracker make_tracker(int id) so that creating one via your function performs zero copies. The test prints the copy count.

Challenge 2

Write Tracker best_of(int a, int b) that creates two local trackers, Tracker x(a) and Tracker y(b), and returns the one with the bigger id, with zero copies. Returning a local variable by name moves it, but return cond ? x : y; does not: that expression is a plain lvalue, so it's copied.

Challenge 3

Write std::vector<Tracker> make_team(int n) returning trackers with ids 1 to n, making zero copies. This Tracker has no move constructor, so push_back(Tracker(i)) copies, and so does the vector when it grows. Build each tracker in place with emplace_back, and reserve room first.

Previous: Move assignment and the rule of five Next: Moved-from objects