当前位置: 首页 > 知识库问答 >
问题:

转发引用是否仍然是rvalue引用?

齐威
2023-03-14

我仍然被那些为了支持移动和转发而发明的规则弄糊涂了。有一件事我还不太确定:

转发引用是否只是rvalue引用(应用了引用折叠规则)?

如果它是一个rvalue引用,那么为什么函数:

template<typename T>
void func(T&&);

不仅接受rvalues,还接受lvalues?

共有2个答案

仲孙经赋
2023-03-14

t被替换之前,t&&是一个rvalue引用(显然)。

T被替换之后(以及在引用折叠之后),T&或者保持rvalue引用(如果T不是引用),或者成为lvalue引用(如果T是lvalue引用)。

苏畅
2023-03-14

我不确定这个答案是否会让你满意,但我可以指出标准的相关部分。简而言之,引用t&&在“语法上”始终是rvalue引用,但有时它最终声明的类型是lvalue引用类型。

当这种情况作为模板参数推演的结果发生时,作为一个方便的速记,整个构造被称为“转发引用”。(这种情况需要引用折叠,但模板参数推演并不是引用折叠发生的唯一时间。)

现在来看看标准的措辞。首先,我们有[dcl.ref](例如p2、p6):

使用&声明的引用类型称为lvalue引用,使用&声明的引用类型称为rvalue引用。[...]

如果typedef-name(9.1.3,13.1)或decltype-specifier(9.1.7.2)表示对t类型的引用tr类型的tr类型,则尝试创建类型“lvalue reference to cvtr”将创建类型“lvalue reference tot”,而尝试创建类型“rvalue reference to cvtr”将创建类型“tr”将创建类型“tr”。[注:此规则称为引用折叠。-结尾注]

最后,模板参数推演的情况在[temp.defint.call]P3中处理:

转发引用是对cv-unqualified模板参数[...]的rvalue引用

换句话说,转发引用是rvalue引用,但它也接受lvalue引用。(请注意,标准的“转发引用”定义实际上并不要求推导模板参数,尽管这是您通常希望触发引用折叠行为的主要方式。)

 类似资料:
  • 假设一个函数有两个重载 然后在另一个函数的主体中 过载<代码>f(T 这让我非常惊讶。一个带有签名

  • 我一直在切换模板工厂函数来使用(和理解)d::f支持右值和移动语义学。我常用的模板类样板工厂函数总是将参数标记为const: 按预期编译。最初,我将MakeMyPair转换为以const形式传递参数,但这不会使用XCode 4.6在我的Mac上编译: 没有用于调用“MakeMyPair\U Forward”候选函数的匹配函数[具有T=int,U=bool]不可行:没有从“int”到“const i

  • 问题内容: 据我所知,使用旧的JMM来实现懒惰单调的DCL(双重检查锁定)技巧被打破了,但是我坚信它已被新的JMM和volatile字段所修复… 但是,在这篇不错的文章中,这显然已经足够新,足以引用DCL中的新旧JMM和volatile字段,表明它仍然坏了… 我在这里到那里读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了? 我的理解是,通过波动性地在关系发生之前保证发生的先兆并有效

  • 问题内容: 是否仍然有效?我想知道本书中描述的思想,概念和实现是否仍与最新的Java版本兼容。 我问是因为最新版本是2006年完成的。 问题答案: 是的,在我看来仍然有效。从6到7的变化不大。Fork- join是一项新功能,非常适合分治法式的问题。但是本书中所有现有的东西,例如同步,易失性,servlet,仍然非常有效。

  • 我有一个关于转发推荐信的具体问题。(我认为)我理解R值引用和,但理解转发引用有困难: 是,这很好。如果是类型,为什么它打印“lvalue”,而我们需要?我的意思是,从到的转换在哪里?

  • 问题内容: PHP中是否有一种方法可以确定给定变量是否是对另一个变量的引用和/或被另一个变量引用?考虑到php.net上的注释,设置可能意味着“ $ a和$ b在这里完全相等。 我可能会无法分开检测“对……的引用”和“对……的引用” 。$ a并不指向$ b或反之亦然。$ a和$ b指向同一位置。 ” 如果无法确定给定变量是否是引用/引用,是否存在一种通用方法来确定两个变量是否是彼此引用?再次,对p