C/C++ Arena

Step 6 of 7

Sink parameters and emplace_back

When a function or constructor is going to keep a string (store it in a member or a container), how should it take the parameter?

#include <iostream>
#include <string>
#include <utility>
#include <vector>

class Contact {
public:
    Contact(std::string name, std::string phone)
        : name_(std::move(name)), phone_(std::move(phone)) {}
    std::string line() const { return name_ + ": " + phone_; }

private:
    std::string name_;
    std::string phone_;
};

int main() {
    std::vector<Contact> book;
    std::string mine = "Ada";
    book.emplace_back(mine, "555-0101");        // mine is copied once; we still have it
    book.emplace_back("Grace", "555-0199");     // built in place from the literals
    book.push_back(Contact("Linus", "555-0142"));  // builds a temporary, then moves it in
    for (const auto& c : book) std::cout << c.line() << "\n";
    std::cout << "still have " << mine << "\n";
}
Ada: 555-0101
Grace: 555-0199
Linus: 555-0142
still have Ada

The cost for each kind of caller

emplace_back vs push_back

Use emplace_back when you have constructor arguments rather than an existing object.

Common mistake

Taking a parameter by value and then not moving it: name_(name) copies again. The std::move in the initializer is what makes the sink pattern pay off.

Your task

Give Player a sink constructor, and write void recruit(std::vector<Player>& team, std::string name) that adds a player using emplace_back and moves the name.

Challenge 2

Give Team two sink functions: set_name(std::string name) and add_tag(std::string tag), which moves the tag into the tags_ vector. Both must move their parameter, so a caller who passes std::move(s) never pays for a copy.

Challenge 3

Write void add_points(std::map<std::string, int>& scores, std::string name, int pts). If name is new, insert it with pts, moving the name into the map. If it's already there, add pts to the existing score. Use try_emplace, which returns {iterator, inserted} and only uses its arguments when the key is new.

Previous: Moved-from objects Next: Challenge: a move-aware log