# 深入浅出C++11:右值引用、移动语义与完美转发详解
## 引言:C++11现代化的核心变革
C++11标准的发布标志着C++语言的一次重大革新,其中右值引用、移动语义、可变参数模板和完美转发构成了现代C++编程的核心基石。这些特性不仅优化了性能,还引入了全新的编程范式。理解这些概念不仅是掌握现代C++的必经之路,更是编写高效、优雅代码的关键所在。本文将深入解析这些核心特性,从基础概念到高级应用,帮助开发者构建完整的现代C++编程知识体系。
## 右值引用:理解值类别的基础
### 1. 左值、右值与右值引用的基本概念
在深入右值引用之前,必须理解C++中的值类别(value categories)。
```cpp
#include <iostream>
#include <utility>
// 左值:有名字、有地址、可被取地址的对象
void demonstrate_lvalue() {
int x = 10; // x是左值
int& ref = x; // 左值引用
x = 20; // 可以修改
int* ptr = &x; // 可以取地址
std::cout << "x的地址: " << ptr << std::endl;
}
// 右值:临时对象,即将销毁的对象
void demonstrate_rvalue() {
int x = 10; // x是左值
int y = 20; // y是左值
// 以下表达式产生右值
int z = x + y; // x+y的结果是右值
// 字面量是右值
42; // 整数字面量是右值
"hello"; // 字符串字面量是右值
// 函数返回非引用类型产生右值
auto get_value = []() { return 100; };
int result = get_value(); // get_value()返回右值
}
// 右值引用:绑定到右值的引用
void demonstrate_rvalue_reference() {
int x = 10;
// 左值引用
int& lref = x; // 正确:左值引用绑定左值
// int& lref2 = 10; // 错误:左值引用不能绑定右值
// 右值引用
int&& rref1 = 10; // 正确:右值引用绑定右值
int&& rref2 = x + 5; // 正确:绑定到表达式结果
// const左值引用可以绑定右值
const int& cref = 10; // 正确
std::cout << "右值引用示例:\n";
std::cout << "rref1: " << rref1 << std::endl;
std::cout << "rref2: " << rref2 << std::endl;
}
// 判断值类别的实用函数
template<typename T>
void check_value_category(T&& param) {
std::cout << "参数类型推导: ";
if (std::is_lvalue_reference<T&&>::value) {
std::cout << "左值引用";
} else if (std::is_rvalue_reference<T&&>::value) {
std::cout << "右值引用";
} else {
std::cout << "普通类型";
}
std::cout << std::endl;
}
int main() {
demonstrate_lvalue();
demonstrate_rvalue();
demonstrate_rvalue_reference();
int x = 10;
check_value_category(x); // 左值
check_value_category(10); // 右值
check_value_category(x + 5); // 右值
return 0;
}
```
### 2. 右值引用的高级应用
右值引用不仅仅是一种新的引用类型,它开启了移动语义的可能性。
```cpp
#include <iostream>
#include <vector>
#include <string>
class ResourceHolder {
private:
int* data;
size_t size;
public:
// 构造函数
explicit ResourceHolder(size_t s) : size(s) {
data = new int[size];
std::cout << "构造函数: 分配 " << size << " 个元素" << std::endl;
}
// 拷贝构造函数(深拷贝)
ResourceHolder(const ResourceHolder& other) : size(other.size) {
data = new int[size];
std::copy(other.data, other.data + size, data);
std::cout << "拷贝构造函数" << std::endl;
}
// 移动构造函数(关键:使用右值引用)
ResourceHolder(ResourceHolder&& other) noexcept
: data(other.data), size(other.size) {
// 转移资源所有权
other.data = nullptr;
other.size = 0;
std::cout << "移动构造函数" << std::endl;
}
// 拷贝赋值运算符
ResourceHolder& operator=(const ResourceHolder& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new int[size];
std::copy(other.data, other.data + size, data);
std::cout << "拷贝赋值运算符" << std::endl;
}
return *this;
}
// 移动赋值运算符
ResourceHolder& operator=(ResourceHolder&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
std::cout << "移动赋值运算符" << std::endl;
}
return *this;
}
// 析构函数
~ResourceHolder() {
delete[] data;
std::cout << "析构函数" << std::endl;
}
void fill(int value) {
std::fill(data, data + size, value);
}
void print() const {
std::cout << "数据: [";
for (size_t i = 0; i < std::min(size, size_t(5)); ++i) {
std::cout << data[i] << " ";
}
if (size > 5) std::cout << "...";
std::cout << "]" << std::endl;
}
};
// 测试右值引用的优势
void test_resource_management() {
std::cout << "\n=== 资源管理测试 ===" << std::endl;
// 创建对象
ResourceHolder holder1(1000000);
holder1.fill(42);
// 拷贝构造 - 昂贵的深拷贝
std::cout << "\n拷贝构造测试:" << std::endl;
ResourceHolder holder2 = holder1; // 拷贝构造函数
// 移动构造 - 高效的资源转移
std::cout << "\n移动构造测试:" << std::endl;
ResourceHolder holder3 = std::move(holder1); // 移动构造函数
// 验证移动后原对象状态
std::cout << "\n移动后holder1的状态:" << std::endl;
// holder1.print(); // 危险:holder1已被移动
// 在容器中使用
std::cout << "\n容器中的移动语义:" << std::endl;
std::vector<ResourceHolder> containers;
// 添加临时对象 - 触发移动构造
containers.push_back(ResourceHolder(500000));
// 使用std::move移动现有对象
ResourceHolder holder4(300000);
containers.push_back(std::move(holder4));
}
// 右值引用在函数参数中的应用
class StringProcessor {
public:
// 接受左值引用 - 可能需要拷贝
void process_copy(const std::string& str) {
std::string local_copy = str; // 发生拷贝
std::cout << "处理拷贝: " << local_copy << std::endl;
}
// 重载版本:接受右值引用 - 可以移动
void process_copy(std::string&& str) {
std::string local_copy = std::move(str); // 移动而非拷贝
std::cout << "处理移动: " << local_copy << std::endl;
}
// 优化版本:统一处理左值和右值
void process_optimal(std::string str) {
// str已经是拷贝或移动的结果
std::cout << "优化处理: " << str << std::endl;
}
};
int main() {
test_resource_management();
StringProcessor processor;
std::string text = "Hello, World!";
std::cout << "\n=== 字符串处理测试 ===" << std::endl;
processor.process_copy(text); // 调用左值版本
processor.process_copy("Temporary"); // 调用右值版本
processor.process_optimal(text); // 拷贝构造
processor.process_optimal("Temporary"); // 移动构造
return 0;
}
```
## 移动语义:性能优化的革命
### 1. std::move的本质与使用
移动语义的核心在于`std::move`,理解其本质至关重要。
```cpp
#include <iostream>
#include <vector>
#include <memory>
#include <utility>
// std::move的简单实现(理解其本质)
namespace my_std {
template<typename T>
typename std::remove_reference<T>::type&& move(T&& arg) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(arg);
}
}
// 移动语义的深入理解
class Buffer {
private:
char* data;
size_t size;
public:
Buffer(size_t sz) : size(sz) {
data = new char[size];
std::cout << "Buffer构造: " << size << " 字节" << std::endl;
}
// 移动构造函数
Buffer(Buffer&& other) noexcept
: data(other.data), size(other.size) {
other.data = nullptr;
other.size = 0;
std::cout << "Buffer移动构造" << std::endl;
}
// 移动赋值运算符
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
std::cout << "Buffer移动赋值" << std::endl;
}
return *this;
}
~Buffer() {
delete[] data;
std::cout << "Buffer析构" << std::endl;
}
// 禁用拷贝(只允许移动)
Buffer(const Buffer&) = delete;
Buffer& operator=(const Buffer&) = delete;
};
// std::move的正确使用场景
void demonstrate_move_usage() {
std::cout << "\n=== std::move使用示例 ===" << std::endl;
// 场景1:将本地变量移动到容器中
{
Buffer local_buffer(1024);
std::vector<Buffer> buffers;
// 错误:不能拷贝(拷贝构造函数被删除)
// buffers.push_back(local_buffer);
// 正确:使用std::move
buffers.push_back(std::move(local_buffer));
std::cout << "移动后,local_buffer不再拥有资源" << std::endl;
}
// 场景2:函数返回局部对象
auto create_buffer = [](size_t size) -> Buffer {
Buffer buffer(size);
// 不需要std::move,编译器会自动优化
return buffer; // 可能触发RVO或移动
};QT.W4E.HK|WL.E8P.HK|VY.R6T.HK|
Buffer received_buffer = create_buffer(2048);
// 场景3:交换两个对象
auto swap_buffers = [](Buffer& a, Buffer& b) {
Buffer temp = std::move(a);
a = std::move(b);
b = std::move(temp);
};
Buffer buffer1(512);
Buffer buffer2(256);
swap_buffers(buffer1, buffer2);
}
// 移动语义在智能指针中的应用
void demonstrate_smart_pointer_moves() {
std::cout << "\n=== 智能指针的移动语义 ===" << std::endl;
// unique_ptr只能移动,不能拷贝
auto ptr1 = std::make_unique<int>(42);
std::cout << "ptr1: " << *ptr1 << std::endl;
// 移动所有权
auto ptr2 = std::move(ptr1);
std::cout << "移动后:" << std::endl;
std::cout << "ptr1: " << (ptr1 ? "有效" : "无效") << std::endl;
std::cout << "ptr2: " << *ptr2 << std::endl;
// shared_ptr可以拷贝,但移动更高效
auto shared1 = std::make_shared<std::string>("Hello");
auto shared2 = shared1; // 拷贝:引用计数增加
auto shared3 = std::move(shared1); // 移动:引用计数不变
std::cout << "shared1移动后: " << (shared1 ? "有效" : "无效") << std::endl;
}
// 移动语义的陷阱与注意事项
class MovableResource {
std::unique_ptr<int[]> data;
size_t size;
public:
MovableResource(size_t s) : size(s) {
data = std::make_unique<int[]>(size);
std::cout << "分配资源" << std::endl;
}
// 移动后对象应处于有效状态
MovableResource(MovableResource&& other) noexcept
: data(std::move(other.data)), size(other.size) {
other.size = 0; // 重要:移动后设置有效状态
std::cout << "移动构造" << std::endl;
}
// 移动赋值
MovableResource& operator=(MovableResource&& other) noexcept {
if (this != &other) {
data = std::move(other.data);
size = other.size;
other.size = 0; // 重要:移动后设置有效状态
std::cout << "移动赋值" << std::endl;
}
return *this;
}
// 移动后对象应该可以被安全析构
~MovableResource() {
std::cout << "析构,size = " << size << std::endl;
}
bool is_valid() const {
return data != nullptr && size > 0;
}
};
void demonstrate_move_pitfalls() {
std::cout << "\n=== 移动语义的注意事项 ===" << std::endl;
MovableResource res1(100);
MovableResource res2 = std::move(res1);
std::cout << "移动后res1是否有效: " << (res1.is_valid() ? "是" : "否") << std::endl;
std::cout << "移动后res2是否有效: " << (res2.is_valid() ? "是" : "否") << std::endl;
// 安全使用移动后的对象
if (!res1.is_valid()) {
std::cout << "res1已被移动,不应再使用" << std::endl;
}
}
int main() {
demonstrate_move_usage();
demonstrate_smart_pointer_moves();
demonstrate_move_pitfalls();
return 0;
}
```
### 2. 移动语义与标准库容器
现代C++标准库充分利用了移动语义来优化性能。
```cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <chrono>
// 测试移动语义对容器性能的影响
class HeavyObject {
std::vector<int> data;
std::string name;
public:
HeavyObject(std::string n, size_t size) : name(std::move(n)) {
data.resize(size);
std::fill(data.begin(), data.end(), 42);
}
// 移动构造函数
HeavyObject(HeavyObject&& other) noexcept
: data(std::move(other.data)), name(std::move(other.name)) {
std::cout << "移动构造: " << name << std::endl;
}
// 拷贝构造函数
HeavyObject(const HeavyObject& other)
: data(other.data), name(other.name) {
std::cout << "拷贝构造: " << name << std::endl;
}
size_t get_size() const { return data.size(); }
};
void test_container_performance() {
std::cout << "\n=== 容器性能测试 ===" << std::endl;
// 准备测试数据
std::vector<HeavyObject> objects;
objects.reserve(100); // 预分配空间避免多次重分配
auto start = std::chrono::high_resolution_clock::now();
// 插入临时对象 - 应该使用移动语义
for (int i = 0; i < 100; ++i) {
objects.emplace_back("Object_" + std::to_string(i), 10000);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::cout << "插入100个对象耗时: " << duration.count() << "ms" << std::endl;
}
// 移动语义在算法中的应用
void demonstrate_algorithm_moves() {
std::cout << "\n=== 算法中的移动语义 ===" << std::endl;
std::vector<std::string> words = {"apple", "banana", "cherry", "date", "elderberry"};
// std::move与算法结合
std::vector<std::string> moved_words;
moved_words.reserve(words.size());
// 移动所有元素到新容器
std::move(words.begin(), words.end(), std::back_inserter(moved_words));
std::cout << "移动后原容器大小: " << words.size() << std::endl;
std::cout << "原容器内容: ";
for (const auto& w : words) {
std::cout << "\"" << w << "\" "; // 已移动,可能为空
}
std::cout << std::endl;
std::cout << "新容器内容: ";
for (const auto& w : moved_words) {
std::cout << "\"" << w << "\" ";
}
std::cout << std::endl;
// 使用std::make_move_iterator
std::vector<std::string> source = {"one", "two", "three"};
std::vector<std::string> destination;
destination.insert(
destination.end(),
std::make_move_iterator(source.begin()),
std::make_move_iterator(source.end())
);
std::cout << "\n使用make_move_iterator后:" << std::endl;
std::cout << "source: ";
for (const auto& s : source) {
std::cout << "\"" << s << "\" ";
}
std::cout << std::endl;
}
// 移动语义与异常安全
class ExceptionSafeResource {
std::unique_ptr<int[]> data;
size_t size;
public:
ExceptionSafeResource(size_t s) : size(s) {
data = std::make_unique<int[]>(size);
std::cout << "构造完成" << std::endl;
}
// noexcept移动构造函数
ExceptionSafeResource(ExceptionSafeResource&& other) noexcept
: data(std::move(other.data)), size(other.size) {
other.size = 0;
}
// 带异常抛出的操作
void risky_operation() {
if (size > 1000) {
throw std::runtime_error("资源太大!");
}
}
// 交换操作(异常安全)
friend void swap(ExceptionSafeResource& a, ExceptionSafeResource& b) noexcept {
using std::swap;
swap(a.data, b.data);
swap(a.size, b.size);
}
};
void demonstrate_exception_safety() {
std::cout << "\n=== 异常安全与移动语义 ===" << std::endl;
try {
ExceptionSafeResource res1(500);
ExceptionSafeResource res2(1500);
// 由于res2.risky_operation()可能抛出异常,
// 使用移动语义可以保证异常安全
ExceptionSafeResource temp = std::move(res2);
temp.risky_operation(); // 可能抛出异常
// 只有不抛出异常才交换
swap(res1, temp);
} catch (const std::exception& e) {
std::cout << "异常捕获: " << e.what() << std::endl;
}
}
int main() {
test_container_performance();
demonstrate_algorithm_moves();
demonstrate_exception_safety();
return 0;
}
```
## 可变参数模板:类型安全的可变参数
### 1. 可变参数模板基础
可变参数模板提供了类型安全的可变参数机制。
```cpp
#include <iostream>
#include <string>
#include <tuple>
// 基本可变参数模板
template<typename... Args>
void print_all(Args... args) {
std::cout << "参数数量: " << sizeof...(args) << std::endl;
}
// 递归展开可变参数模板
// 递归终止函数
void print_recursive() {
std::cout << std::endl;
}
// 递归展开函数
template<typename T, typename... Args>
void print_recursive(T first, Args... rest) {
std::cout << first << " ";
print_recursive(rest...);
}
// 使用折叠表达式(C++17)
template<typename... Args>
void print_fold(Args... args) {
// 一元右折叠
(std::cout << ... << args) << std::endl;
}
// 带分隔符的打印
template<typename... Args>
void print_with_separator(const std::string& sep, Args... args) {
bool first = true;
auto print_with_sep = [&](const auto& arg) {
if (!first) std::cout << sep;
first = false;
std::cout << arg;
};
// C++17折叠表达式
(print_with_sep(args), ...);
std::cout << std::endl;
}
// 可变参数模板的元编程
template<typename... Args>
struct TypeInfo {
static constexpr size_t count = sizeof...(Args);
static void print() {
std::cout << "包含 " << count << " 个类型" << std::endl;
}
};
// 类型列表操作
template<typename... Ts>
struct TypeList {};
// 获取第一个类型
template<typename T, typename... Ts>
struct FirstType {
using type = T;
};
// 获取最后一个类型
template<typename... Ts>
struct LastType;
template<typename T>
struct LastType<T> {
using type = T;
};
template<typename T, typename... Ts>
struct LastType<T, Ts...> {
using type = typename LastType<Ts...>::type;
};
// 测试可变参数模板
void test_variadic_templates() {
std::cout << "=== 可变参数模板测试 ===" << std::endl;
print_all(); // 参数数量: 0
print_all(1, 2.5, "hello"); // 参数数量: 3
std::cout << "\n递归展开: ";
print_recursive(1, 2.5, "hello", 'a');
std::cout << "折叠表达式: ";
print_fold(1, " + ", 2, " = ", 3);
std::cout << "带分隔符: ";
print_with_separator(", ", 1, 2, 3, 4, 5);
// 类型信息
TypeInfo<int, double, std::string>::print();
// 类型列表
using MyTypes = TypeList<int, double, std::string>;
using First = FirstType<int, double, std::string>::type;
using Last = LastType<int, double, std::string>::type;
std::cout << "第一个类型: " << typeid(First).name() << std::endl;
std::cout << "最后一个类型: " << typeid(Last).name() << std::endl;
}
```
### 2. 可变参数模板与完美转发的结合
```cpp
#include <iostream>
#include <memory>
#include <functional>
// 完美转发包装器
template<typename Func, typename... Args>
auto forward_wrapper(Func&& func, Args&&... args)
-> decltype(func(std::forward<Args>(args)...)) {
std::cout << "调用函数,参数数量: " << sizeof...(args) << std::endl;
return func(std::forward<Args>(args)...);
}
// 通用工厂函数
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// 日志装饰器
template<typename Func>
class LogDecorator {
Func func;
std::string name;
public:
LogDecorator(Func f, std::string n)
: func(std::move(f)), name(std::move(n)) {}
template<typename... Args>
auto operator()(Args&&... args)
-> decltype(func(std::forward<Args>(args)...)) {
std::cout << "[" << name << "] 开始执行" << std::endl;
auto result = func(std::forward<Args>(args)...);
std::cout << "[" << name << "] 执行完成" << std::endl;
return result;
}
};
// 自动创建日志装饰器
template<typename Func>
auto make_logger(Func&& func, std::string name) {
return LogDecorator<std::decay_t<Func>>(
std::forward<Func>(func),
std::move(name)
);
}
// 测试函数
int add(int a, int b) {
return a + b;
}
std::string concat(const std::string& a, const std::string& b) {
return a + b;
}
void test_perfect_forwarding() {
std::cout << "\n=== 完美转发测试 ===" << std::endl;
// 完美转发包装器测试
auto result1 = forward_wrapper(add, 10, 20);
std::cout << "add(10, 20) = " << result1 << std::endl;
auto result2 = forward_wrapper(concat, "Hello, ", "World!");
std::cout << "concat = " << result2 << std::endl;
// 工厂函数测试
struct Point {
int x, y;
Point(int x, int y) : x(x), y(y) {
std::cout << "构造Point(" << x << ", " << y << ")" << std::endl;
}
};
auto point = make_unique<Point>(3, 4);
std::cout << "Point: (" << point->x << ", " << point->y << ")" << std::endl;
// 日志装饰器测试
auto logged_add = make_logger(add, "加法函数");
auto sum = logged_add(5, 7);|NH.P8H.HK|XR.E2C.HK|ZQ.W4E.HK
std::cout << "带日志的加法结果: " << sum << std::endl;
}
// 可变参数模板的编译期计算
template<typename... Args>
constexpr size_t calculate_size() {
return (sizeof(Args) + ...); // C++17折叠表达式
}
// 编译期类型检查
template<typename... Args>
struct AllIntegral {
static constexpr bool value = (std::is_integral_v<Args> && ...);
};
void test_compile_time_features() {
std::cout << "\n=== 编译期特性测试 ===" << std::endl;
// 编译期计算大小
constexpr size_t total_size = calculate_size<int, double, char>();
std::cout << "类型总大小: " << total_size << " 字节" << std::endl;
// 编译期类型检查
std::cout << std::boolalpha;
std::cout << "All integral<int, double>: "
<< AllIntegral<int, double>::value << std::endl;
std::cout << "All integral<int, short>: "
<< AllIntegral<int, short>::value << std::endl;
}
int main() {
test_variadic_templates();
test_perfect_forwarding();
test_compile_time_features();
return 0;
}
```
## 完美转发:保持值类别的艺术
### 1. 完美转发的实现原理
完美转发是C++模板编程中的高级技术,理解其原理至关重要。
```cpp
#include <iostream>
#include <utility>
#include <type_traits>
// 完美转发的基本实现
template<typename T>
void forward_value(T&& arg) {
// T&& 是通用引用,可以绑定左值和右值
process(std::forward<T>(arg));
}
// 处理左值引用
void process(int& x) {
std::cout << "处理左值引用: " << x << std::endl;
x = 100; // 可以修改
}
// 处理右值引用
void process(int&& x) {
std::cout << "处理右值引用: " << x << std::endl;
// x是右值引用,可以安全地移动
}
// 处理const左值引用
void process(const int& x) {
std::cout << "处理const左值引用: " << x << std::endl;
}
// 测试完美转发
void test_perfect_forwarding_basic() {
std::cout << "=== 完美转发基础测试 ===" << std::endl;
int x = 42;
const int y = 100;
// 测试各种值类别
forward_value(x); // 左值
forward_value(123); // 右值
forward_value(y); // const左值
forward_value(std::move(x)); // 显式右值
std::cout << "修改后x的值: " << x << std::endl;
}
// 通用引用与模板参数推导
template<typename T>
void demonstrate_universal_reference(T&& param) {
std::cout << "\n通用引用测试:" << std::endl;
std::cout << "T的类型: " << typeid(T).name() << std::endl;
std::cout << "param的类型: " << typeid(param).name() << std::endl;
// 使用std::forward保持值类别
if (std::is_lvalue_reference<T>::value) {
std::cout << "参数是左值引用" << std::endl;
} else {
std::cout << "参数是右值引用" << std::endl;
}
}
// 引用折叠规则
template<typename T>
void reference_collapsing_example(T&& arg) {
// 引用折叠规则:
// T& & -> T&
// T& && -> T&
// T&& & -> T&
// T&& && -> T&&
using NoRef = std::remove_reference_t<T>;
if constexpr (std::is_same_v<T, NoRef&>) {
std::cout << "T是左值引用类型" << std::endl;
} else if constexpr (std::is_same_v<T, NoRef&&>) {
std::cout << "T是右值引用类型" << std::endl;
} else {
std::cout << "T是非引用类型" << std::endl;
}
}
void test_reference_collapsing() {
std::cout << "\n=== 引用折叠测试 ===" << std::endl;
int x = 42;
int& lref = x;
int&& rref = 100;
reference_collapsing_example(x); // T推导为int&
reference_collapsing_example(123); // T推导为int&&
reference_collapsing_example(lref); // T推导为int&
reference_collapsing_example(rref); // T推导为int&
}
// 完美转发在构造函数中的应用
class PerfectForwardingClass {
std::string data;
public:
// 完美转发构造函数
template<typename T,
typename = std::enable_if_t<
std::is_constructible_v<std::string, T&&>
>>
explicit PerfectForwardingClass(T&& str)
: data(std::forward<T>(str)) {
std::cout << "完美转发构造函数" << std::endl;
std::cout << "参数类型: " << typeid(T).name() << std::endl;
}
// 拷贝构造函数(需要显式定义)
PerfectForwardingClass(const PerfectForwardingClass& other)
: data(other.data) {
std::cout << "拷贝构造函数" << std::endl;
}
// 移动构造函数
PerfectForwardingClass(PerfectForwardingClass&& other) noexcept
: data(std::move(other.data)) {
std::cout << "移动构造函数" << std::endl;
}
void print() const {
std::cout << "数据: " << data << std::endl;
}
};
void test_perfect_forwarding_constructor() {
std::cout << "\n=== 完美转发构造函数测试 ===" << std::endl;
// 各种构造方式
PerfectForwardingClass obj1("临时字符串"); // 右值
obj1.print();
std::string str = "左值字符串";
PerfectForwardingClass obj2(str); // 左值
obj2.print();
PerfectForwardingClass obj3(obj1); // 拷贝构造
obj3.print();
PerfectForwardingClass obj4(std::move(obj2)); // 移动构造
obj4.print();
}
int main() {
test_perfect_forwarding_basic();
test_reference_collapsing();
test_perfect_forwarding_constructor();
// 通用引用演示
int value = 42;
demonstrate_universal_reference(value);
demonstrate_universal_reference(123);
return 0;
}
```
### 2. 完美转发的实际应用
完美转发在现代C++库设计中有着广泛应用。
```cpp
#include <iostream>
#include <vector>
#include <memory>
#include <functional>
#include <tuple>
// 通用工厂模式
template<typename Base, typename... Args>
class Factory {
public:
template<typename Derived>
static std::unique_ptr<Base> create(Args&&... args) {
static_assert(std::is_base_of_v<Base, Derived>,
"Derived must be derived from Base");
return std::make_unique<Derived>(std::forward<Args>(args)...);
}
};
// 产品基类
class Product {
public:|TC.E8P.HK|JY.R6T.HK|
virtual ~Product() = default;
virtual void use() = 0;
};
// 具体产品
class ConcreteProductA : public Product {
std::string name;
int value;
public:
ConcreteProductA(std::string n, int v) : name(std::move(n)), value(v) {
std::cout << "构造ConcreteProductA: " << name << std::endl;
}
void use() override {
std::cout << "使用产品A: " << name << ", 值: " << value << std::endl;
}
};
class ConcreteProductB : public Product {
double price;
public:
explicit ConcreteProductB(double p) : price(p) {
std::cout << "构造ConcreteProductB: 价格 " << price << std::endl;
}
void use() override {
std::cout << "使用产品B: 价格 " << price << std::endl;
}
};
// 回调系统
template<typename... Args>
class CallbackSystem {
std::vector<std::function<void(Args...)>> callbacks;
public:
// 注册回调
template<typename Func>
void register_callback(Func&& func) {
callbacks.emplace_back(std::forward<Func>(func));
}
// 触发回调
void trigger(Args&&... args) {
for (auto& callback : callbacks) {
callback(std::forward<Args>(args)...);
}
}
size_t count() const { return callbacks.size(); }
};
// 通用包装器
template<typename Func>
class FunctionWrapper {
Func func;
public:
template<typename F>
FunctionWrapper(F&& f) : func(std::forward<F>(f)) {}
template<typename... Args>
auto operator()(Args&&... args)
-> decltype(func(std::forward<Args>(args