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?
const std::string&avoids a copy on the way in, but then storing it must copy.- The sink pattern: take it by value, and
std::moveit into place. The caller decides whether that by-value parameter is filled by a copy (if they still need their string) or by a move (if they pass a temporary or usestd::move).
#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
- Passing a variable you still need: exactly one copy (into the parameter), then a cheap move into the member. You can't do better, since two strings must exist.
- Passing a temporary or
std::move(x): zero copies, just moves.
emplace_back vs push_back
push_back(obj)takes a finished object and copies or moves it into the vector.emplace_back(args...)passesargsstraight to the element's constructor, building it inside the vector's memory. No temporary object at all.
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 turn: 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.
Previous: Moved-from objects Next: Challenge: a move-aware log