C/C++ Arena

Step 5 of 7

Moved-from objects

After b = std::move(a);, what is a? For standard library types the rule is valid but unspecified:

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

int main() {
    std::vector<std::string> inbox = {"hi", "lunch?", "meeting at 3"};

    std::vector<std::string> archive = std::move(inbox);   // steal the whole buffer
    inbox.clear();                                          // now definitely empty
    std::cout << archive.size() << " archived, inbox " << inbox.size() << "\n";

    inbox.push_back("new mail");                            // reusing it is fine
    std::cout << inbox[0] << "\n";

    std::string draft = "unsent text";
    archive.push_back(std::move(draft));                    // move one element in
    draft = "fresh draft";                                  // assign a new value: fine
    std::cout << archive.back() << " / " << draft << "\n";
}
3 archived, inbox 0
new mail
unsent text / fresh draft

How it works

The professional habit

After moving from something, either stop using it or reset it explicitly (clear(), assignment). Code that reads a moved-from value may work today and break on another compiler.

A function can also move out of a reference parameter, as your task does. That's powerful but surprising for the caller, so name such functions clearly (take_all, release, drain), so readers know the argument will be emptied.

Your turn: write std::vector<std::string> take_all(std::vector<std::string>& src) that moves the whole contents out of src (no element copies) and leaves src definitely empty.

Previous: Return by value is free Next: Sink parameters and emplace_back