Hel*_*irr 2 c++ return rvalue lvalue rvalue-reference
在C++ 11中,通常的做法是通过引用将左值传递给函数.
int& f(int& a){
return a;
}
int main(void){
auto a = 1;
auto b = f(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,是否可以通过右值引用将值传递给函数并通过lvalue返回此值?
int& f(int&& a){
return a;
}
int main(void){
auto b = f(1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它为什么或为什么不可能?
这是可能的,但通常是不明智的.这段代码没问题:
#include <utility>
#include <iostream>
int &foo(int &&a) {
return a;
}
int main() {
int a = 1;
std::cout << foo(std::move(a)) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
这段代码也可以:
int main() {
std::cout << foo(1) << "\n";
}
Run Code Online (Sandbox Code Playgroud)
此代码具有未定义的行为:
int main() {
int &a = foo(1); // lifetime of the temporary 1 ends "at the semi-colon"
std::cout << a << "\n";
}
Run Code Online (Sandbox Code Playgroud)
因此,滥用该功能非常容易foo.
至于它工作的原因 - 这里发生的所有事情都是从右值引用到左值引用的隐式转换.如果不允许这样做会很不方便,因为这意味着你不能写:
void bar1(const int &a) {
std::cout << (a + 1) << "\n";
}
void bar2(int &&a) {
bar1(a);
... do destructive stuff with a ...
}
Run Code Online (Sandbox Code Playgroud)
允许隐式转换可能有更强的理由.我不知道官方的动机,这只是我想到的第一个.
即使在C++ 03中也存在相关问题.你可以写:
const int *baz(const int &a) { return &a; }
Run Code Online (Sandbox Code Playgroud)
为了获取指向临时/值的指针 - 该语言阻止您直接执行此操作,如果返回值超出生成它的表达式,则会导致相同的未定义行为.
可以说,禁止&1(采用指针,以文字或其他临时)是一个地方在C++标准不只是假设程序员知道他们在做什么.但我认为历史上它背后的原因是你必须能够对一个临时的const引用,以便运算符重载工作.你不必能够指向临时的指针,C禁止它,因为在C中,整数文字永远不需要有一个内存位置.所以C++继续禁止它,即使在C++中你确实引用了一个整数文字,那么编译器可能会被迫创建一个包含该值的实际位置.Stroustrup可能会对指向整数字的指针说同样的话,但没有必要.