C++

Lesson 03

Move semantics and lifetimes

Move owned values into long-lived objects instead of storing references that can outlive the caller.

Good Code

src/review_batch.cpp
#include <string>
#include <utility>
#include <vector>

struct Review {
    std::string title;
};

class ReviewBatch {
public:
    explicit ReviewBatch(std::vector<Review> reviews)
        : reviews_(std::move(reviews))
    {
        // Moving owned input gives the batch a stable lifetime.
    }

private:
    std::vector<Review> reviews_;
};

Bad Code

review_batch.cpp
#include <string>
#include <vector>

struct Review {
    std::string title;
};

class ReviewBatch {
public:
    explicit ReviewBatch(const std::vector<Review>& reviews)
        : reviews_(reviews)
    {
        // Reference storage can outlive the caller's vector.
    }

private:
    const std::vector<Review>& reviews_;
};

Review Notes

What to review

Good Code

The good version takes the vector by value and moves it into the batch. The class owns its data, so it can safely outlive the call site.

Bad Code

The bad version stores a reference member. If the caller passes a temporary or a local vector, the batch later reads through a dangling reference.

Takeaways

  • Reference members are lifetime contracts; prefer owned values when the object needs data after the caller returns.