C++ 11 - 返回由左值传递给函数的rvalue?

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)

它为什么或为什么不可能?

Ste*_*sop 5

这是可能的,但通常是不明智的.这段代码没问题:

#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可能会对指向整数字的指针说同样的话,但没有必要.