首页 > 其他分享 >完美转发(模板)--T&&

完美转发(模板)--T&&

时间:2024-10-07 11:23:41浏览次数:7  
标签:std 右值 -- && 转发 forward 模板

在C++模板编程中,完美转发(Perfect Forwarding)是一种技术,旨在保留函数参数的值类别,即在将参数传递到另一个函数时,无论参数是左值还是右值,都能够保持它的原始性质,而不会因为转发丢失性能或引入不必要的拷贝。

完美转发的关键在于通过模板的转发引用(Forwarding Reference),结合 std::forward,将参数以最合适的形式传递给目标函数。

为什么需要完美转发?

在某些情况下,我们希望编写一个通用的函数模板,这个函数模板接收一个可调用对象,并将参数传递给这个可调用对象。
为了避免不必要的拷贝(尤其是右值被拷贝的情况),我们需要一种机制来将参数的值类别保持下来,这就是完美转发的目的。

什么是转发引用?

当一个模板参数被定义为 T&& 时,它并不总是表示右值引用。在模板的上下文中,T&& 是一个特殊的类型,称为转发引用(有时也叫万能引用)。它具有这样的行为:

  • 如果传入的是左值T&& 被推导为 T&(左值引用)。
  • 如果传入的是右值T&& 被推导为 T&&(右值引用)。

这使得我们能够编写一个函数模板,既能接受左值参数,又能接受右值参数。

完美转发的核心:std::forward

完美转发的核心技术是通过 std::forward 来实现的。std::forward 是一个标准库函数,它的作用是在模板中根据参数的类型完美地转发参数:

  • 如果参数是左值,std::forward 会保持它为左值。
  • 如果参数是右值,std::forward 会将其转发为右值。

完美转发的使用示例

以下是一个使用完美转发的简单示例:

#include <iostream>
#include <utility>  // for std::forward

// 一个通用的函数模板,用于接收任意的可调用对象和参数,并调用它
template <typename F, typename... Args>
void wrapper(F&& f, Args&&... args) {
    // 使用std::forward来完美转发参数
    std::forward<F>(f)(std::forward<Args>(args)...);
}

// 左值引用和右值引用的两个重载函数
void foo(int& x) {
    std::cout << "Lvalue reference called: " << x << std::endl;
}

void foo(int&& x) {
    std::cout << "Rvalue reference called: " << x << std::endl;
}

int main() {
    int a = 10;
    
    // 调用 wrapper,传递左值
    wrapper(foo, a);   // 输出: Lvalue reference called: 10
    
    // 调用 wrapper,传递右值
    wrapper(foo, 20);  // 输出: Rvalue reference called: 20
    
    return 0;
}

在这个例子中,wrapper 函数模板通过 std::forward 来实现完美转发:

  • wrapper(foo, a) 被调用时,a 是一个左值,因此 foo(int& x) 被调用。
  • wrapper(foo, 20) 被调用时,20 是一个右值,因此 foo(int&& x) 被调用。

通过 std::forward,我们能够在传递参数的过程中避免不必要的拷贝和移动,保持参数的原始值类别。

总结

完美转发是在模板编程中通过转发引用T&&)和 std::forward 来保证参数的值类别(左值或右值)不变的一种技术。
它的目的是在模板函数中高效传递参数,避免不必要的拷贝或移动,进而提高程序性能。

标签:std,右值,--,&&,转发,forward,模板
From: https://www.cnblogs.com/niumachen/p/18449839

相关文章

  • 重启后,idea 依赖爆红
    没改动代码,但无法运行java项目java:-source1.5中不支持……表达式/运算符java:错误:不支持发行版本5解决:https://www.cnblogs.com/liu-han/p/16105953.html文件→项目结构,SDK和项目/模块语言级别的版本要一致SDK:1.8项目语言级别:SDK默认值模块语言级别:SDK默认值......
  • BTS24
    B.BacktoSchool'24P2-Cheating题目描述有\(N\)道题,第\(i\)道题的分值为\(A_i(A_1\leA_2\le\dots\leA_N)\),有\(M\)个学生,初始时分数均为\(0\)。每次会让分数最低的\(B_i\)个同学获得\(A_i\)分,若有多个分数相同的学生,则让编号更小的学生获得\(A_i\)分。求......
  • 0x01 解决梯度消失和梯度爆炸的常用方法
    一、输入层初始化权重对于较深的网络,Xavier初始化和Kaiming初始化是常用的方法。Xavier假设输入和输出的方差相等,它特别适用于sigmoid和tanh激活函数,因为它能帮助保持信号在这些激活函数中传播时的方差不变,防止梯度消失或爆炸。Kaiming特别设计用于ReLU及其变体......
  • linux中的source命令和bash命令各有什么作用
    在Linux中,`source`命令和`bash`命令都是用来执行shell脚本或者设置环境变量的,它们在Shell编程和日常的系统管理任务中经常被用到。下面我简要解释一下这两个命令的作用:1.`source`命令:使用`source`命令可以读取并执行一个shell脚本文件中的命令,就好像脚本中的命令是直接在当......
  • WPF MVVM第一篇-MVVM框架搭建
    1.创建view界面<Windowx:Class="WpfFramework.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schema......
  • 如何去除Windows10文件资源管理器上的6个文件夹:桌面、视频、图片、文档、下载、音乐和
    尽管 Win10 提供了迄今为止最先进和丰富的功能,但并不是每一个人都希望其预装那么多的组件。长期以来,微软通常会在Windows资源管理器中包含6个“桌面、文档、下载、音乐、图片和视频”的默认存储位置。在2017年10月的“秋季创意者更新”之后,它又增加了“3D对象”。其旨在为......
  • Leetcode 10. 正则表达式匹配
    1.题目基本信息1.1.题目描述给你一个字符串s和一个字符规律p,请你来实现一个支持‘.’和‘*’的正则表达式匹配。‘.’匹配任意单个字符‘*’匹配零个或多个前面的那一个元素所谓匹配,是要涵盖整个字符串s的,而不是部分字符串。1.2.题目地址https://leetcode.c......
  • [亲测]君临九州+单机安装教程+无需虚拟机+GM后台
    今天给大家带来一款单机游戏的架设:君临九州,版本号:1.0.12.30。另外:本人承接各种游戏架设(单机+联网)本人为了学习和研究软件内含的设计思想和原理,带了架设教程仅供娱乐。教程是本人亲自搭建成功的,绝对是完整可运行的,踩过的坑都给你们填上了。如果你是小白也没问题,跟着教程走也是可......
  • 教资 - 综合(1)
    1、教育政策制定的各个阶段,都要实行大众参与,集体领导和少数服从多数的原则指的是(民主原则)2、教育政策的制定要有利于促进教育事业的发展指的是(效益原则)3、在教育政策制定过程中核心环节是(设计和论证教育政策方案)4、任何政策都有其适用范围指的是教育政策执行的(对象的适用性)5、......
  • JUCE - 入门
    注:本文档由JUCE官方教程翻译而来。JUCE官网:https://juce.com1、开始使用Projucer本教程将向您展示如何安装JUCE以及如何使用Projucer创建新的跨平台JUCE项目。您还将学习如何将项目导出到IDE(例如Xcode或VisualStudio)以开发、运行和调试您的JUCE应用程序。级别:初......