【问题标题】:C++0x: rvalue reference versus non-const lvalueC++0x:右值引用与非常量左值
【发布时间】:2010-12-23 18:43:08
【问题描述】:

在 C++03 中编程时,我们不能将未命名的临时 T() 传递给函数 void foo(T&);。通常的解决方案是给临时命名,然后像这样传递它:

T v;
foo(v);

现在,C++0x 出现了——现在有了右值引用,定义为 void foo(T&&) 的函数将允许我传递一个临时值。这让我想到了我的问题:由于一个接受右值引用的函数既可以接受右值引用(未命名的临时对象)也可以接受左值引用(命名的非常量引用),是否有任何理由在函数参数中再使用左值引用?我们不应该总是使用右值作为函数参数吗?

当然,一个接受左值引用的函数会阻止调用者传递一个临时值,但我不确定这是否是一个有用的限制。

【问题讨论】:

  • 如果例程试图存储参数的地址以供将来在某处使用,这将是一个非常有用的限制。

标签: c++ c++11 lvalue rvalue-reference


【解决方案1】:

“因为采用右值引用的函数既可以采用右值引用(未命名的临时对象)也可以采用左值引用(命名的非常量引用)”

这是一个错误的陈述。在右值参考规范的第一次迭代中,这是正确的,但它不再是并且至少在 MSVC 中实现以符合后来的变化。换句话说,这是非法的:

void f(char&&);

char x;
f(x);

为了调用一个期望右值引用的函数,你必须像这样把它变成一个右值:

f(std::move(x))

当然,该语法清楚地表明了一个函数采用左值引用和一个采用右值引用的函数之间的真正区别是:右值引用不希望在调用中继续存在。这是一件大事。

现在,您当然可以创建一个新函数来完全执行 std::move 所做的工作,然后您“可以”使用类似于左值引用的右值引用。例如,我考虑过使用访问者框架执行此操作,有时您根本不关心访问者调用的任何结果,但有时您会这样做,因此在这些情况下需要左值引用。使用右值引用,我可以同时得到这两者……但这违反了右值引用语义,我认为这是个坏主意。

基于此,您的陈述可能会造成混淆:

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

char x;
f(x);

这可行,但不是因为您将左值作为右值引用传递。它的工作原理是参考衰减(C++0x 中也是新的)。当您将左值传递给这样的模板时,它实际上会像这样被实例化:

void f<char&>(char&&&);

引用衰减表明&amp;&amp;&amp; 变成了&amp;,所以实际的实例化如下所示:

void f<char&>(char&);

换句话说,您只是通过引用传递一个左值......这没有什么新的或特别的。

希望能解决问题。

【讨论】:

    【解决方案2】:

    如果必须主动处理该临时文件,例如指向new 内存的指针或文件句柄等有限资源,这是一个有用的限制。但是需要传递这些回传的气味更像是“糟糕的设计”而不是“有用的限制”。

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 2023-03-16
      相关资源
      最近更新 更多