测试_第19章_移动语义.cpp

← 测试总览 · 目录

编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第19章_移动语义.cpp -o t && ./t(需先 cd 测试/

// 第19章测试:移动语义与完美转发
#include <print>
#include <string>
#include <vector>
#include <numeric>
#include <chrono>
#include <algorithm>
#include <memory>
#include <utility>

int failures = 0;
#define CHECK(expr)                                                         \
    do {                                                                    \
        if (!(expr)) {                                                      \
            ++failures;                                                     \
            std::println("FAIL 第{}行: {}", __LINE__, #expr);              \
        }                                                                   \
    } while (0)

// 19.4 完整 Buffer 类
class Buffer {
public:
    explicit Buffer(std::size_t size = 0) : size_(size) {
        if (size_) data_ = new char[size_];
    }
    // 拷贝构造:深复制
    Buffer(const Buffer& other)
        : size_(other.size_) {
        if (size_) {
            data_ = new char[size_];
            std::copy(other.data_, other.data_ + size_, data_);
        }
    }
    // 移动构造:偷资源
    Buffer(Buffer&& other) noexcept
        : data_(other.data_), size_(other.size_) {
        other.data_ = nullptr;
        other.size_ = 0;
    }
    // 移动赋值
    Buffer& operator=(Buffer&& other) noexcept {
        if (this != &other) {
            delete[] data_;
            data_ = other.data_;
            size_ = other.size_;
            other.data_ = nullptr;
            other.size_ = 0;
        }
        return *this;
    }
    ~Buffer() { delete[] data_; }
    std::size_t size() const { return size_; }
    char* data() { return data_; }
    void swap_dummy() { *this = Buffer{}; }         // 移动赋值自己
private:
    char* data_ = nullptr;
    std::size_t size_ = 0;
};

// 19.3 计数类:观察操作发生
struct Tracker {
    static inline int copies = 0;
    static inline int moves = 0;
    int value = 0;
    Tracker(int v) : value(v) {}
    Tracker(const Tracker& o) : value(o.value) { ++copies; }
    Tracker(Tracker&& o) noexcept : value(o.value) { ++moves; o.value = -1; }
    Tracker& operator=(const Tracker& o) { value = o.value; ++copies; return *this; }
    Tracker& operator=(Tracker&& o) noexcept { value = o.value; ++moves; o.value = -1; return *this; }
};

// 19.6 完美转发:分类重载
std::string classify(std::string&)  { return "左值"; }
std::string classify(std::string&&) { return "右值"; }

template <typename T>
std::string wrapper(T&& arg) {
    return classify(std::forward<T>(arg));
}

// 19.8 计时包装器
template <typename F, typename... Args>
auto time_it(const char* name, F&& f, Args&&... args) {
    auto start = std::chrono::steady_clock::now();
    auto result = std::forward<F>(f)(std::forward<Args>(args)...);
    auto end = std::chrono::steady_clock::now();
    std::println("{} 耗时 {} 微秒", name,
                 std::chrono::duration_cast<std::chrono::microseconds>(end - start).count());
    return result;
}

int main() {
    // 19.1 左值/右值基本判断
    int a = 42;
    (void)&a;                                       // 左值可取地址(编译期验证)
    int b = a + 1;                              // a+1 是右值,赋给 b
    CHECK(b == 43);

    // 19.2 右值引用
    int&& r = 42;
    CHECK(r == 42);

    // 19.3 std::move 使能移动
    Tracker t1{1};
    Tracker t2 = std::move(t1);                 // 移动构造
    CHECK(Tracker::moves == 1);
    CHECK(t1.value == -1);                      // 被移动后置空
    t1 = t2;                                    // 拷贝赋值(左值)
    CHECK(Tracker::copies == 1);

    // 临时对象自动移动
    std::vector<Tracker> vec;
    vec.push_back(Tracker{5});                  // 临时 → 移动
    CHECK(Tracker::moves == 2);

    // 19.4 Buffer 正确性
    {
        Buffer src(100);
        Buffer dst = std::move(src);            // 移动构造
        CHECK(dst.size() == 100);
        CHECK(src.size() == 0);                 // 原对象置空
        Buffer t(1);
        t = std::move(dst);                     // 移动赋值
        CHECK(t.size() == 100);
        // 自移动安全性由"this != &other"保护(上方代码)
        Buffer self(1);
        self.swap_dummy();
    }                                           // 无崩溃即双重释放修复
    static_assert(std::is_nothrow_move_constructible_v<Buffer>);

    // 19.5 返回局部对象(C++17 RVO 保证,此处至少不拷贝出问题)
    auto make = [] { Tracker local{7}; return local; };
    Tracker rvo = make();
    CHECK(rvo.value == 7);

    // 19.6 完美转发
    std::string s = "x";
    CHECK(wrapper(s) == "左值");
    CHECK(wrapper(std::move(s)) == "右值");
    CHECK(wrapper(std::string("tmp")) == "右值");

    // 19.8 计时包装器
    std::vector<int> v(1'000'000);
    std::iota(v.begin(), v.end(), 0);
    auto mx = time_it("求最大值", [&] {
        return *std::ranges::max_element(v);
    });
    CHECK(mx == 999999);

    if (failures == 0) std::println("全部通过");
    return failures;
}