2025-12-02 深入浅出C++11:右值引用、移动语义与完美转发详解

# 深入浅出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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容