8

(ほぼ) 同じように扱われるべきだと思う 3 つの関数呼び出しがありますが、明らかにそうではありません。3 つのうちの 1 つがコンパイルされない理由を理解しようとしています (g++ -std=c++0x)。

// Minimal example to reproduce a compile bug I want to understand.

#include <iostream>
#include <string>

using namespace std;


void bar(const string &&x) { cout << "bar: " << x << endl; }

string returns_a_string() { return string("cow"); }

int main( int argc, char *argv[] )
{
    bar(string("horse"));     // ok
    bar(returns_a_string());  // ok
    string aardvark = "aardvark";
    bar(aardvark);            // not ok, fails to compile, error in next comment
    /*
      rvalue-min.cpp:29:22: error: cannot bind ‘std::string {aka std::basic_string<char>}’ lvalue to ‘const string&& {aka const std::basic_string<char>&&}’
      rvalue-min.cpp:10:6: error:   initializing argument 1 of ‘void barR(const string&&)’
    */
}

この質問は C++0x rvalue references - lvalues-rvalue bindingの行に少し沿っていますが、そこに回答がある場合は、申し訳ありませんが、抽出できませんでした。

私が望むのは、関数 bar() を任意の種類の文字列で呼び出して、それを機能させることです。を定義するだけで十分void barR(const string &x)ですが、その理由を本当に理解したいです。

3 番目の呼び出しが異なる理由を理解していただき、ありがとうございます。

4

2 に答える 2

18

右辺値参照パラメーターの目的は、オブジェクトが右辺値である場合を具体的に検出することです。オブジェクトが右辺値である場合、関数はそれが再び使用されないことを認識しているため、それを使用して必要なことを何でも実行できます。左辺値が右辺値参照にバインドできる場合、それは、私が話していた検出が実際には行われていないことを意味します。

これらの関数のいずれかに左辺値を渡したい場合は、 を使用する必要がありますstd::movestd::move右辺値の参照を取る関数を介してオブジェクトを渡すことは、「このオブジェクトを取り出して、内臓を切り取ってください。何が起こるかは気にしません」と言っているようなものです。

あなたの目的のために、正しい答えは、パラメーターを const 参照にすることです。r 値は、const 参照にバインドされていることを完全に満足しています。移動コンストラクターを除いて、右辺値参照パラメーターを作成することは、ほとんど正しいことではありません。

于 2012-01-13T14:02:34.923 に答える
5

を使用する必要がありますstd::move。これはうまくいきます:

bar(std::move(aardvark));
于 2012-01-13T14:00:02.027 に答える