それは可能ですが、通常は賢明ではありません。このコードはOKです:
#include <utility>
#include <iostream>
int &foo(int &&a) {
return a;
}
int main() {
int a = 1;
std::cout << foo(std::move(a)) << "\n";
}
このコードもOKです:
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++標準がプログラマーが何をしているのかを知っていると単に想定していない1つの場所であると言えます。しかし、歴史的にその背後にある理由は、演算子のオーバーロードが機能するためには、一時的なものへのconst参照を取得できる必要があるということだと思います。一時へのポインタを取得できる必要はありません。Cでは整数リテラルにメモリ位置が必要ないため、Cはそれを禁止しています。したがって、C ++では整数リテラルへの参照を取得すると、コンパイラはその値を含む実際の場所を作成するように強制される可能性がありますが、C++は引き続きそれを禁止します。Stroustrupはおそらく可能性があります整数リテラルへのポインタを取ることについても同じことを言っていますが、必要はありませんでした。