Ownership
Move Semantics
Moving transfers ownership from one object to another.
move
`std::move` allows movable objects such as `std::unique_ptr` to transfer ownership.
Move Semantics
move_semantics.cpp
Replay: real traced execution (multi-file project)
#include <iostream>
#include <memory>
#include <string>
int main() {
std::string name = "cache";
std::unique_ptr<std::string> original = std::make_unique<std::string>(name);
std::unique_ptr<std::string> moved = std::move(original);
std::cout << "originalEmpty=" << (original == nullptr) << std::endl;
std::cout << "movedValue=" << *moved << std::endl;
return 0;
}
#include <iostream>
#include <memory>
#include <string>
int main() {
std::string name = "report";
std::unique_ptr<std::string> original = std::make_unique<std::string>(name);
std::unique_ptr<std::string> moved = std::move(original);
std::cout << "originalEmpty=" << (original == nullptr) << std::endl;
std::cout << "movedValue=" << *moved << std::endl;
return 0;
}
#include <iostream>
#include <memory>
#include <string>
int main() {
std::string name = "token";
std::unique_ptr<std::string> original = std::make_unique<std::string>(name);
std::unique_ptr<std::string> moved = std::move(original);
std::cout << "originalEmpty=" << (original == nullptr) << std::endl;
std::cout << "movedValue=" << *moved << std::endl;
return 0;
}
name ← cache, original ← (empty), moved ← (empty)
5int main() {6 std::string name→ cache = "cache"; //@name="report", "token"78 std::unique_ptr<std::string> original→ (empty) = std::make_unique<std::string>(namecache);9 std::unique_ptr<std::string> moved→ (empty) = std::move(original(empty));1011 std::cout << "originalEmpty=" << (original(empty) == nullptr) << std::endl;12 std::cout << "movedValue=" << *moved(empty) << std::endl;13 return 0;14}outputoriginalEmpty=1 movedValue=cache
name ← report, original ← (empty), moved ← (empty)
5int main() {6 std::string name→ report = "report";78 std::unique_ptr<std::string> original→ (empty) = std::make_unique<std::string>(namereport);9 std::unique_ptr<std::string> moved→ (empty) = std::move(original(empty));1011 std::cout << "originalEmpty=" << (original(empty) == nullptr) << std::endl;12 std::cout << "movedValue=" << *moved(empty) << std::endl;13 return 0;14}outputoriginalEmpty=1 movedValue=report
name ← token, original ← (empty), moved ← (empty)
5int main() {6 std::string name→ token = "token";78 std::unique_ptr<std::string> original→ (empty) = std::make_unique<std::string>(nametoken);9 std::unique_ptr<std::string> moved→ (empty) = std::move(original(empty));1011 std::cout << "originalEmpty=" << (original(empty) == nullptr) << std::endl;12 std::cout << "movedValue=" << *moved(empty) << std::endl;13 return 0;14}outputoriginalEmpty=1 movedValue=token
Follow the Move
namestarts ascache.originalowns a heap string with valuecache.std::move(original)transfers that ownership intomoved.originalbecomes empty, sooriginal == nullptrprints1.movednow owns the string, so*movedprintscache. | name | before move owner | after move owner | originalEmpty | movedValue | | --- | --- | --- | ---: | --- | | cache | original | moved | 1 | cache | | report | original | moved | 1 | report | | token | original | moved | 1 | token |
Exercise: move_semantics.cpp
Reproduce originalEmpty=1 and movedValue=cache, then use names report and token to predict the movedValue line.