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