56 C++ 现代C++编程艺术5-万能引用

C++ 现代C++编程艺术5-万能引用

文章目录

  • [C++ 现代C++编程艺术5-万能引用](#C++ 现代C++编程艺术5-万能引用)
    • [一、引用基础进阶 📚](#一、引用基础进阶 📚)
      • [1. 常量引用(const lvalue reference)](#1. 常量引用(const lvalue reference))
      • [2. 右值引用(rvalue reference)](#2. 右值引用(rvalue reference))
      • [3. 引用作为返回值](#3. 引用作为返回值)
    • 二、万能引用🔮
      • [1. 核心定义](#1. 核心定义)
      • [2. 运作原理(引用折叠)](#2. 运作原理(引用折叠))
      • [3. 完美转发(Perfect Forwarding)](#3. 完美转发(Perfect Forwarding))
    • [三、高级技巧组合应用 ⚙️](#三、高级技巧组合应用 ⚙️)
      • [1. SFINAE + 引用控制](#1. SFINAE + 引用控制)
      • [2. 引用限定成员函数](#2. 引用限定成员函数)
      • [3. Lambda捕获引用陷阱](#3. Lambda捕获引用陷阱)
    • [四、性能与安全性指南 🎯](#四、性能与安全性指南 🎯)
    • [五、现代C++演进(C++20/23) 🌐](#五、现代C++演进(C++20/23) 🌐)

一、引用基础进阶 📚

1. 常量引用(const lvalue reference)

cpp 复制代码
void process(const std::string& str) {
    // 可接受:左值、右值、临时对象 
    // 保证不修改原始数据 
}

特性:

  • ✅ 可绑定左值/右值
  • 🛡️ 防止意外修改
  • ⚡ 避免拷贝开销(尤其大型对象)

2. 右值引用(rvalue reference)

cpp 复制代码
void consume(std::string&& str) {
    // 仅接受右值(临时对象)
    // 可安全"窃取"资源(移动语义)
    data_ = std::move(str); 
}

应用场景:

  • 🚀 实现移动构造函数/赋值运算符
  • ⏱️ 高性能资源转移(如vector扩容)

3. 引用作为返回值

cpp 复制代码
class Matrix {
    double& operator()(int i, int j) { 
        return data_[i*cols_+j]; 
    }
};
// 支持链式赋值:mat(2,3) = 1.5;

注意:

⚠️ 禁止返回局部变量的引用

二、万能引用🔮

1. 核心定义

cpp 复制代码
template<typename T>
void magic(T&& param) {  // "T&&" 是万能引用 
    // 根据传入实参自动推导:
    // • 左值 → T 推导为 Type& (左值引用)
    // • 右值 → T 推导为 Type  (普通类型)
}

2. 运作原理(引用折叠)

传入实参类型 T 推导结果 T&& 最终类型
int (右值) int int&&
int&(左值) int& int&
int&&(右值) int int&&

关键公式:

T&& + 左值引用 → 触发引用折叠 → 左值引用

3. 完美转发(Perfect Forwarding)

cpp 复制代码
template<typename... Args>
auto make_wrapper(Args&&... args) {
    return Wrapper(std::forward<Args>(args)...);
}

组件:

  • 🧬 std::forward<Args>(args):保持值类别(左值/右值)
  • 📦 参数包Args&&...:支持任意数量参数

三、高级技巧组合应用 ⚙️

1. SFINAE + 引用控制

cpp 复制代码
template<typename T>
auto process(T&& val) -> std::enable_if_t<
    std::is_integral_v<std::decay_t<T>>, void 
> {
    // 仅接受整型(过滤引用/const修饰)
}

2. 引用限定成员函数

cpp 复制代码
class Data {
    void save() & {  // 左值对象调用 
        std::cout << "保存到持久存储\n";
    }
    void save() && { // 右值对象调用 
        std::cout << "保存后立即销毁资源\n";
    }
};
// 用法:
Data d; 
d.save();           // 调用左值版本 
Data().save();      // 调用右值版本 

3. Lambda捕获引用陷阱

cpp 复制代码
auto create_handlers() {
    std::vector<Handler> handlers;
    for(int i=0; i<10; ++i) {
        // 错误:捕获局部引用i(悬空引用)
        handlers.push_back([&](){ use(i); }); 

        // 正确:值捕获当前状态 
        handlers.push_back([i](){ use(i); });
    }
    return handlers;
}

四、性能与安全性指南 🎯

  1. 引用使用黄金法则

    场景 推荐方式 风险规避措施
    只读访问大型对象 const T& 避免临时对象生命周期
    函数内部修改参数 T& 前置空指针检查
    资源转移 T&& 移动后置为nullptr
    模板参数转发 T&& + forward 禁用不完全类型
  2. 典型错误案例

    cpp 复制代码
    // 陷阱1:返回临时对象引用 
    const std::string& get_name() { 
        return "Alice";  // 临时对象销毁 → 悬空引用 
    }
    
    // 陷阱2:万能引用误用 
    template<typename T>
    void store(T&& data) {
        cache_ = data;  // 左值→深拷贝,右值→错失移动机会 
        // 正确:cache_ = std::forward<T>(data);
    }

五、现代C++演进(C++20/23) 🌐

  1. 概念约束(Concepts)优化万能引用

    cpp 复制代码
    template<std::movable T>  // 明确要求可移动类型 
    void transfer(T&& obj) {
        target_ = std::forward<T>(obj);
    }
  2. Deducing this(C++23)

    cpp 复制代码
    class Button {
        void click(this auto&& self) {
            // 自动推导调用者值类别 
            if constexpr (std::is_lvalue_reference_v<decltype(self)>) {
                log("左键点击");
            } else {
                log("临时按钮触发");
            }
        }
    };
  3. 引用技术💎

    技术 关键语法 核心作用 应用频率
    常量引用 const T& 安全只读访问 ⭐⭐⭐⭐⭐
    右值引用 T&& 资源移动/性能优化 ⭐⭐⭐⭐
    万能引用 T&&(模板上下文) 完美转发/类型推导 ⭐⭐⭐⭐
    引用折叠 typedef T& &T& 支撑万能引用机制 ⭐⭐
    引用限定成员函数 void func() & 区分左值/右值对象行为 ⭐⭐
相关推荐
2401_8762213420 分钟前
Reachability Query(Union-Find)
c++·算法
yueyuebaobaoxinx2 小时前
MATLAB 与 Simulink 联合仿真:控制系统建模与动态性能优化
开发语言·matlab·性能优化
躲着人群3 小时前
次短路&&P2865 [USACO06NOV] Roadblocks G题解
c语言·数据结构·c++·算法·dijkstra·次短路
superlls3 小时前
(计算机网络)JWT三部分及 Signature 作用
java·开发语言·计算机网络
小欣加油4 小时前
leetcode 1493 删掉一个元素以后全为1的最长子数组
c++·算法·leetcode
liulilittle4 小时前
.NET反射与IL反编译核心技术
开发语言·数据库·c#·.net·反射·反编译·il
扛麻袋的少年5 小时前
6.Kotlin的Duration类
android·开发语言·kotlin
争不过朝夕,又念着往昔5 小时前
即时通讯项目---网关服务
linux·c++·vscode
蓝风破云5 小时前
C++实现常见的排序算法
数据结构·c++·算法·排序算法·visual studio