完美转发(模板)--T&&
在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 来保证参数的值类别(左值或右值)不变的一种技术。
它的目的是在模板函数中高效传递参数,避免不必要的拷贝或移动,进而提高程序性能。
完美转发(模板)--T&&的更多相关文章
- C++11新特性 变参模板、完美转发(简述)
变参模板 (Variadic Template) - 使得 emplace 可以接受任意参数,这样就可以适用于任意对象的构建 完美转发 - 使得接收下来的参数 能够原样的传递给对象的构造函数,这带来另 ...
- [C++中级进阶]001_C++0x里的完美转发到底是神马?
[C++中级进阶]001_C++0x里的完美转发到底是神马? 转载至:http://www.cnblogs.com/alephsoul-alephsoul/archive/2013/01/10/285 ...
- 翻译「C++ Rvalue References Explained」C++右值引用详解 Part8:Perfect Forwarding(完美转发):解决方案
本文为第八部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...
- 第16课 右值引用(3)_std::forward与完美转发
1. std::forward原型 template <typename T> T&& forward(typename std::remove_reference< ...
- (原创)C++11改进我们的程序之move和完美转发
本次要讲的是右值引用相关的几个函数:std::move, std::forward和成员的emplace_back,通过这些函数我们可以避免不必要的拷贝,提高程序性能.move是将对象的状态或者所有权 ...
- c++11 标准库函数 std::move 和 完美转发 std::forward
c++11 标准库函数 std::move 和 完美转发 std::forward #define _CRT_SECURE_NO_WARNINGS #include <iostream> ...
- 完美转发(perfect forwarding)、universal reference、引用折叠(collasping)
首先要分清: C++里的值只有两种值:左值.右值.—— 其本质应该是内存中存储的值/instance分两种:一种是持久的,一种是“短暂的” 也只有两种引用: 左值引用.右值引用. ——引用,就是这个内 ...
- [c++11]右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- [转][c++11]我理解的右值引用、移动语义和完美转发
c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能.有点难理解,于是花时间整理一下自己的理解. 左值.右值 C++中所有的值都必然属于左值.右值二者之一.左值是指表达式结束后依然存在的 ...
- Effective Modern C++:05右值引用、移动语义和完美转发
移动语义使得编译器得以使用成本较低的移动操作,来代替成本较高的复制操作:完美转发使得人们可以撰写接收任意实参的函数模板,并将其转发到目标函数,目标函数会接收到与转发函数所接收到的完全相同的实参.右值引 ...
随机推荐
- 【工具】SpringBoot项目如何查看某个maven依赖是否存在以及依赖链路
当我在SpringBoot项目中想加个依赖,但是不确定现有依赖的依赖的依赖.....有没有添加过这个依赖,怎么办呢?如果添加过了但是不知道我需要的这个依赖属于哪个依赖的下面,怎么查呢? IDEA中提供 ...
- Miniconda 切换python版本
要在 Miniconda 中切换 Python 版本,可以按照以下步骤进行操作: 打开命令提示符或者 Anaconda Prompt(如果已经安装了). 输入 conda info --envs 查看 ...
- java程序设计期末复习总结&复盘
java复习 java的特点:简单.面向对象.可移植.跨平台.分布式.多线程.稳定安全.高性能 一个数组可以存放许多不同类型的数值. (F) StringBuffer类是线程安全的,StringBui ...
- 为团队配置Linux环境,简单高效的项目共享方案
前言 最近好久没写博客了,事情太多了,我还搞了个新的好玩的项目,等后续做得差不多了来写篇文章介绍一下. 在我们目前的AI项目中,团队需要共同使用一台GPU服务器来做模型训练和数据处理.为了让每个团队成 ...
- 【Java】Spring注入静态Bean的几种写法
单例模式在Spring注解上的一种拓展用法 写法一,先配置自身Bean,作为静态成员,然后目标Bean作为自身Bean的实例成员' Spring初始化自身Bean时自动装配数据源Bean,从而附属到静 ...
- 【Uni-App】其他配置笔记
manifest.json manifest.json 文件是应用的配置文件,用于指定应用的名称.图标.权限等.HBuilderX 创建的工程此文件在根目录,CLI 创建的工程此文件在 src 目录. ...
- 【SpringBoot】日志在项目中的应用
日志的目的: 为了方便日后的运维,快速定位BUG,错误信息等等 日志算是一个救命稻草 pom.xml需要的依赖: <?xml version="1.0" encoding=& ...
- 【JS】06 语法补充
严格模式(use strict) 其实就是就是对JS随意的语法做一个强制规范要求 开启严格模式: "use strict"; 注意,只有在第一行声明才会有效,. 否则在严格模式之前 ...
- 【Git】下载安装(Linux)
安装CentOS8貌似有自带Git 可以先查看一下有没有 git --version 有或者没有都行,有的话安装就当是更新 没有就装,yum提供了安装,我们不需要自己压缩包安装了 yum instal ...
- 人形机器人sim2real —— 致使现实环境与仿真环境下的差距的因素 —— sim2real
下图引自:https://b2b.baidu.com/q/aland?q=7B7474317C2E72330F621B0F7D6F09247E747E610623742B&id=qid599a ...