首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如果在std::apply中使用forward_as_tuple结果之前将其存储在变量中,则会丢失右值引用

std::apply是C++17标准库中的一个函数模板,用于将一个函数应用于一个参数包中的参数。forward_as_tuple是C++11中引入的一个函数模板,用于将参数包中的参数转发为std::tuple对象,保持参数的值Category是完美转发。

在使用std::apply时,如果将forward_as_tuple的结果存储在一个变量中,那么会丢失右值引用。这是因为forward_as_tuple返回的是一个std::tuple对象,而在将std::tuple对象赋值给变量时,会发生拷贝构造。拷贝构造会将右值引用转变为左值,因此右值引用会丢失。

举个例子来说明,在下面的代码中:

代码语言:txt
复制
#include <tuple>
#include <iostream>
#include <utility>

void func(int&& i) {
    std::cout << i << std::endl;
}

int main() {
    int i = 10;
    std::apply(func, std::forward_as_tuple(std::move(i)));  // 此处会丢失右值引用
    return 0;
}

在调用std::apply时,我们使用std::forward_as_tuple将i转发为std::tuple<int&&>。但是,由于将forward_as_tuple的结果存储在一个变量中,它会被拷贝构造为一个std::tuple<int>对象,这会导致右值引用丢失。所以当func函数被调用时,输出的结果是10,而不是预期的右值引用值。

解决这个问题的方法是直接在std::apply中使用std::forward_as_tuple,而不是将其结果存储在变量中。这样就可以保持右值引用。修改后的代码如下:

代码语言:txt
复制
#include <tuple>
#include <iostream>
#include <utility>

void func(int&& i) {
    std::cout << i << std::endl;
}

int main() {
    int i = 10;
    std::apply(func, std::forward_as_tuple(std::move(i)));
    return 0;
}

在这个例子中,func函数被调用时,输出的结果是预期的右值引用值10。这是因为我们直接在std::apply中使用了std::forward_as_tuple,没有将其结果存储在变量中,所以右值引用得以保留。

腾讯云相关产品和产品介绍链接地址暂不提供,请根据具体需求和场景自行选择适合的云计算产品和服务。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

c++17好用的新特性总结

使用auto关键字能够提高编码效率,同时能够简化重构流程。但是,C++11的auto推导,往往结果与预期的不同。 c++11 为了支持统一初始化,引入了新的统一初始化语法,如下所示。...2. lambda表达式 lambda也是c++11引入的,C++11,lambda表达式只能用捕获this,this是当前对象的一个只读的引用。...C++17之前,我们定义全局变量, 总需要将变量定义cpp文件,然后通过extern关键字来告诉编译器 这个变量已经在其他地方定义过了。...c++17之前,只能自己通过独占锁和条件变量自己实现读写锁或使用c++14加入的性能较差的std::shared_timed_mutex。...常用于可能失败的函数的返回,比如工厂函数。C++17之前,往往使用T*作为返回,如果为nullptr则代表函数失败,否则T*指向了真正的返回

3.3K10

C++STL之 tuple

C++ tuple  的使用说明 c++的tuple是一个允许存放多种不同的数据类型的容器,是针对pair的泛型,和pair一样std 的namespace使用的时候,需要引用头文件,同时注意...需要注意的是,tuple变量的元素数量,创建完成后就是固定不变的,不能增加或减少。...,c) = tup; std::cout<<"a="<<a<<" "<<"b="<<b<<" "<<"c="<<c<<endl; 程序的输出<em>结果</em>为a=l b=6 c=2.33 如果不想取某一位的<em>值</em>,可以<em>使用</em>...<<"a="<<a<<" "<<"c="<<c<<endl; 程序的输出<em>结果</em>为a=l c=2.33 3.forward_as_tuple 用于接收<em>右</em><em>值</em><em>引用</em>数据生成tuple auto tup = <em>std</em>...可以看出,tuple<em>中</em>的参数全部为<em>右</em><em>值</em><em>引用</em>。

39820
  • C++17 在业务代码中最好用的十个特性

    ); } clang 环境下,可以 lambda 表达式捕获时显式引入一个引用变量通过编译 for(const auto& [key, value]: map){     [&key = key,... c++17 之前,只能自己通过独占锁和条件变量自己实现读写锁或使用 c++14 加入的性能较差的std::shared_timed_mutex。...是一个可以存储任何可拷贝类型的容器,C 语言中通常使用void*实现类似的功能,与void*相比,std::any具有两点优势: std::any更安全:类型 T 被转换成void*时,T 的类型信息就已经丢失了...常用于可能失败的函数的返回,比如工厂函数。 C++17 之前,往往使用T*作为返回,如果为nullptr则代表函数失败,否则T*指向了真正的返回。...通过使用std::variant,用户可以实现类似 Rust 的std::result,即在函数执行成功时返回结果失败时返回错误信息,上文的例子则可以改成: std::variant

    2.6K20

    【重学C++】04 | 说透C++引用(上)

    ; // ok, rfoo()是int* p2 = &rfoo(); // error, rfoo()是,无法获取内存地址左引用 vs 引用C++引用是一种别名,可以通过一个变量名访问另一个变量...图片上图中,变量a和变量b指向同一块内存地址,也可以说变量a是变量b的别名。C++引用分为左引用引用两种类型。...左引用是指对左进行引用引用类型,通常使用&符号定义;引用是指对进行引用引用类型,通常使用&&符号定义。...、表达式结果、临时对象等这类无法通过&符号获取变量内存地址的,称为。...实际效果与上面的推论相反,bar中使用std::move反倒多余了。现代C++编译器会有返回优化。换句话说,编译器将直接在foo返回的位置构造x对象,而不是本地构造x然后将其复制出去。

    20000

    C++11知识点总结(全面解析C++11经常考到的知识点)

    9.1 引用概念 C++98提出了引用的概念,引用即别名,引用变量与其引用实体公共同一块内存空间,而引用的底层是通过指针来实现的,因此使用引用,可以提高程序的可读性。...如果表达式的运行结果是一个临时变量或者对象,认为是。 如果表达式运行结果或单个变量是一个引用则认为是左。...总结: 不能简单地通过能否放在=左侧右侧或者取地址来判断左或者,要根据表达式结果变量的性质判断,比如上述:c常量 能得到引用的表达式一定能够作为引用,否则就用常引用。...C++11引用:只能引用,一般情况不能直接引用。...int main() { // 10纯,本来只是一个符号,没有具体的空间, // 引用变量r1定义过程,编译器产生了一个临时变量,r1实际引用的是临时变量 int&&

    2.1K10

    Chapter 5: Rvalue References, Move Semantics, PF

    std::move无条件的把它的参数转换成一个,而std::forward特定条件下将参数转换成。...,右边是,是内容 string s = "whitewall"; //为了实现移动构造,需要将左变量内容 //传给移动构造函数的引用 A b(std::...Use std::move on rvalue references, std::forward on universal references 转发引用时,引用应当无条件地被转换成,而通用引用应当有条件地被转换成仅当它们绑定到上时...在编译器为类自动生成移动和拷贝构造函数时,也不能使用重载过的通用引用参数构造函数,因为通用引用参数的构造函数匹配顺序上会在其他重载函数之前。...折叠引用的规则如下: 如果有一个引用是左引用,那么结果就是左引用。 否则,结果就是引用,比如两个都是引用时。

    5.1K40

    【C++修炼之路】27.引用

    引用就是对引用,给取别名。 函数返回指的是传返回。之前提到过,调用函数之后会销毁函数栈帧,会生成一个临时对象拷贝函数返回,这个临时变量之所以有常性就是因为其是。...如果不想rr1被修改,可以用const int&& rr1去引用。但实际引用使用场景并不在于此,这根特性也不重要。.../int&& r2 = a;//error // 引用可以引用move以后的左 int&& r3 = std::move(a); return 0; } 二.引用返回的意义 了解引用之前...事实上,对于左引用,最有意义的就是函数传参以及传返回时,通过左引用可以减少拷贝,因为普通的变量实际上都是将传入的参数拷贝到函数参数上或者将返回拷贝到一个临时变量。...这就是我们第六个标题说到的,传参数的过程引用变量接收了,但他会继续传到另一个函数,此时就会因这个具有左属性而被当成左,所以匹配函数的时候调用的仍然是深拷贝,因此,我们在这些移动构造的函数还有要将参数通过

    26400

    不知道这些,别说你会C++

    START unsetunset左unsetunset C++ ,左(Lvalue)是指具有标识符(变量名)的表达式,即可以被赋值的表达式。左具有持久的内存地址,可以程序中被引用和修改。...unsetunsetunsetunset C++ (Rvalue)是指无法取地址或临时的表达式,通常是不具有标识符的临时对象、字面量、表达式的计算结果等。...左是指可以取地址的表达式,通常是具有标识符(变量名)的对象,例如变量、函数返回的变量、成员或数组元素等。 左引用的声明语法是类型名称前加上 & 符号。...unsetunset纯unsetunset C++ ,纯(Pure Rvalue)是指临时对象、字面量、表达式的计算结果等不具有标识符的。...它允许将参数以原始的左形式传递给其他函数,而不会丢失参数的类别信息。 完美转发的核心概念是使用通用引用(Universal Reference),即通过 T&& 的形式来声明参数。

    14310

    【C++】C++11常用特性总结

    实际上以前没有引用的时候,是通过输出型参数来解决传返回代价太大的问题,即在调用函数之前创建好要返回的对象,然后将这个返回的对象通过传引用的方式来传参,函数内部通过改变这个输出型参数的方式来改变函数外面提前创建好的对象或变量...实际上当引用之后,引用对象就丢失的属性,你可以理解为引用之后,会被存储到名为引用对象的一个空间当中,此时rr1和rr2实际就变成了左丢失的属性,rr1和rr2都能够取地址...但非常容易忽略的一个点就是上面我们提到的那个知识点,引用之后,引用实体会丢失属性转而变为左,所以传递引用实体时,我们必须加move,将其属性再变为,这样才能调用到下一个引用版本的接口...上面解决引用过后属性丢失,但是需要连续给多个接口传参的问题时,采用了不断move的方式来解决,以此来保持传递参数过程的属性能够保持不变。...如果此时直接调用Fun,并将t参数传过去,就会发生我们之前所说的问题,引用过后属性丢失引用对象重新变为左,那t就会作为左传递给Fun函数,所以就只能调用到const左引用和左引用版本的

    81140

    再也不用std::thread编写多线程了

    * * @return int */ //3 //std::async默认启动策略使用 thread_local变量时,无法预知会取到的是哪个线程的局部存储 using namespace.../** * @brief * 1,调用方唤起对期望的 get 之前,被调方可能已经执行完毕,因此结果不会存储在被调方的 std::promise型别对象里 * 因为那个对象,对于被调方来说是个局部量...,在被调方结束后会实施析构 * * 2,该结果也不能存储调用方的期望,因为可能会从 std::future型别对象出发创建 std::shared_future型别对象, * 因此把被调方结果的所有权从..., * 因为作为引用的x,复制之前被转换成了) * * 3,最后 push_back返回的那一时刻,tmp被析构,所有,这就需要调用一次std::string的析构函数 */ //因此,有没有办法将字符串字面量直接传递给步骤...,那个Widget都发生了泄露 * * * @return int */ //正确的做法 //从 new Widget获取指针并将其独立语句中转交给资源管理对象,然后该对象作为传递给你最初想要向其传递

    2.4K40

    引⽤与移动语义

    C++,左(lvalue)和(rvalue)是两种不同的表达式类型,它们的主要区别在于它们在内存的状态和使用方式。...& x) f(std::move(x)); // 调⽤ f(int&& x) return 0; } 引⽤和移动语义的使⽤ (重点) 左引用的主要使用场景回顾 左引用主要的使用场景是函数通过左引用传递返回的时候减少拷贝或者传参的时候用左引用接收实参减少拷贝...上文已经提出:引用可以延长对象的生命周期,并且恰好可以直接返回来避免再次构造对象。 实践证明,使用引用来接收返回则会收到空的内容。...引⽤和移动语义传参的提效 STL 容器引用 STL ,许多容器(如 std::list、std::vector 等)增加了支持引用的接口: 当传入一个左时,容器会调用拷贝构造函数... C++ 引用的作用是为了避免不必要的拷贝,直接操作原对象。引用折叠使得模板中使用引用时,能根据实际传入的参数类型自动决定使用引用还是引用,从而提高性能。

    11510

    第 13 章 拷贝控制

    表达式通常表示的是一个对象的身份,不能将其绑定到要求转换的表达式、字面常量和返回的表达式。 返回非引用类型的函数,连同算术、关系、位以及后置递增/递减运算符,都返回。...引用指向将要被销毁的对象,因此可以从绑定到引用的对象“窃取”其状态,也就是移动其数据,而不用发生多余的拷贝与析构操作。 变量是左,因为变量是持久的,直至离开作用域才被销毁。...因此,不能将一个引用直接绑定到一个变量上,即使这个变量引用也不行。...使用 move的代码应该使用 std::move,而不是 move,这是因为具有转换为引用功能的函数就是标准库的函数模板,而不使用 std,则可能引起潜在的名字冲突。...v2 = getVec(cin); // 右侧对象是一个使用移动赋值 使用拷贝并交换技术实现的赋值运算符,如果在同时定义了一个移动构造函数,则该赋值运算符实际上也是一个移动赋值运算符

    1K50

    C++11新特性学习笔记

    C语言中的auto定义了一个自动变量,它是一个自动存储类型,变量存储空间函数执行时被分配,函数结束后被释放。...引用 7.1 左引用引用 7.1.1 左 C语言中,我们常常会提起左(lvalue)、(rvalue)这样的称呼。...左引用是具名变量值的别名,而引用则是不具名(匿名)变量的别名。...T && TR && T && *一旦定义中出现了左引用引用折叠总是优先将其折叠为左引用* C++11std::forward可以保存参数的左特性: #include using...9.2.3.3 lambda类型 lambda表达式的类型C++11被称为“闭包类型”,每一个lambda表达式则会产生一个临时对象()。因此,严格地将,lambda函数并非函数指针。

    2.2K20

    C++11新特性学习笔记

    C语言中的auto定义了一个自动变量,它是一个自动存储类型,变量存储空间函数执行时被分配,函数结束后被释放。...引用 7.1 左引用引用 7.1.1 左 C语言中,我们常常会提起左(lvalue)、(rvalue)这样的称呼。...左引用是具名变量值的别名,而引用则是不具名(匿名)变量的别名。...T && TR && T && *一旦定义中出现了左引用引用折叠总是优先将其折叠为左引用* C++11std::forward可以保存参数的左特性: #include using...9.2.3.3 lambda类型 lambda表达式的类型C++11被称为“闭包类型”,每一个lambda表达式则会产生一个临时对象()。因此,严格地将,lambda函数并非函数指针。

    2.1K20

    【c++】一篇文章带你了解c++11的新特性&&c++11详解

    3.1 auto C++98auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。...7.1 左引用引用 传统的C++语法中就有引用的语法,而C++11新增了的引用语法特性,所以从现在开始我们之前学习的引用就叫做左引用。...int&& r2 = a; // 引用可以引用move以后的左 int&& r3 = std::move(a); return 0; } 7.3 引用使用场景和意义 前面我们可以看到左引用既可以引用和又可以引用...// 模板的万能引用只是提供了能够接收同时接收左引用引用的能力, // 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左, // 我们希望能够传递过程中保持它的左或者的属性...该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量 注意 lambda函数定义,参数列表和返回类型都是可选部分,而捕捉列表和函数体可以为空。

    17610

    【C++】C++11 引用和移动语义

    一、左与左引用 C++11 之前,我们把数据分为常量和变量,而在 C++11 之后,我们将数据分为左; 左是一个表示数据的表达式 (如变量名或解引用的指针),我们可以对左取地址,也可以对左赋值...,然后返回这个寄存器的内容,而寄存器变量是临时变量,临时变量具有常性,属于。...为什么不能取地址: C++则是一个临时使用的、不可寻址的内存没有独立的内存空间,它只是存储寄存器或其他临时内存空间中的一个;我们也不能把放入内存,因为没有确定的内存位置...move以后的左 int&& r3 = std::move(a); return 0; } 四、引用使用场景和意义 1、左引用的短板 我们之前接触到的引用其实都是 (const) 左引用...旅程三:万能引用的设计又带来了新的问题 – 不管是左引用还是引用,其本身都是左,所以往下一层传递时又要面对类型丢失的问题,但是这里使用之前的 move 已经不能解决问题了,所以 C++11 又又又设计出了完美转发

    77210

    、左引用引用、移动语句(2)「建议收藏」

    术语rvalue指的是存储存储某个地址的数据。 rvalue是一个不能赋值的表达式。文字常量和变量都可以作为。当左出现在需要的上下文中时,左将隐式转换为。...它可以是函数的名称或取消引用函数指针的结果。 C语言还区分它对函数指针和对象指针的处理。 另一方面,C ++,返回引用的函数调用是左。否则,函数调用是rvalue表达式。...将亡 C++11之前和C++11的纯是等价的。C++11的将亡是随着引用的引入而新引入的。换言之,“将亡”概念的产生,是由引用的产生而引起的,将亡引用息息相关。...如果允许绑定到非常量则会导致非常危险的情况出现,因为非常量是一个临时对象,非常量左引用可能会使用一个已经被销毁了的临时对象。...这是因为move构造函数,s虽然是一个非常量引用,但其本身却是一个左(是持久对象,可以对其取地址),因此调用*this = s时,会使用拷贝赋值函数而不是move赋值函数,而这已与move构造函数的语义不相符

    2.6K20

    左右引用和移动语义

    左右和左右引用 什么是左呢?一种极不严谨的理解为:赋值的时候,能够被放到等号左边的为左,放在右边的。...,无法取到他们的地址;而对于a、b和c为具体的变量名,存储在内存,可以取到其地址。...因此一般情况下可以根据能否取到地址,来区分左了解左之前,我们首先要知道表达式的概念:由运算符和运算对象构成的计算式(类似数学的算术表达式)。...引用只能绑定到上。 2. 移动语义 未出现引用之前,我们函数调用传参的时候,某些时候可以使用引用传递参数,减少参数多的拷贝对资源的消耗,提高程序的运行效率。...C++11头文件utility声明了std::move()函数,该函数的作用就是类型转换,通过它,我们可以 把一个左将其标记为

    87740
    领券