C++0x : rvalue reference versus non-const lvalue

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

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

T v;
foo(v);

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

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

最佳答案

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

这是一个错误的陈述。在右值引用规范的第一次迭代中,这是正确的,但它不再是并且至少在 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&&&);

引用衰减表明 &&& 变成 & 所以实际的实例化看起来像这样:

void f<char&>(char&);

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

希望能解决问题。

关于C++0x : rvalue reference versus non-const lvalue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4521524/

相关文章:

c++ - 我可以区分一个和多个参数吗?

c++ - 左值需要作为赋值的左操作数 C++ 编译错误

c++ - 前/后增量的左值和右值

c++ - 将右值分配给 'const auto&' 时会发生什么

c++ - 是什么导致了模板和继承中出现这种令人困惑的编译器错误?

c++ - 通过函数传递随机引擎 - 为什么不同的编译器表现不同

c++ - 如何将范围放在枚举上?

c++ - 什么时候应该在函数返回值上使用 std::move?

c++ - 在 C++ 中,如何声明指向类中方法的函数指针?

c++ - 引用对象 vector ?