2

C ++ 11では、参照によって左辺値を関数に渡すのが一般的な方法です。

int& f(int& a){
    return a;
}

int main(void){
    auto a = 1;
    auto b = f(a);
    return 0;
}

ただし、右辺値参照によって関数に値を渡し、左辺値によってこの値を返すことは可能ですか?

int& f(int&& a){
    return a;
}

int main(void){
    auto b = f(1);
    return 0;
}

なぜそれが可能なのか、それとも不可能なのか?

4

2 に答える 2

5

それは可能ですが、通常は賢明ではありません。このコードは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はおそらく可能性があります整数リテラルへのポインタを取ることについても同じことを言っていますが、必要はありませんでした。

于 2013-01-31T12:03:20.337 に答える
1

あなたが所有権を取得する場合、あなたはオブジェクトに対して責任があります。どこかに保存しないと、一時的なものへの参照を返すようなものです。関数スコープが終了すると、「所有」したオブジェクトが破棄されるため、返された参照は無効になります。

于 2013-01-31T12:00:22.193 に答える