编译运行: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;
}