путаница связывания значений в C ++ - PullRequest
8 голосов
/ 13 января 2012

У меня есть три вызова функций, которые, по моему мнению, должны рассматриваться (примерно) одинаково, но, очевидно, это не так.Я пытаюсь понять, почему один из трех не компилируется (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 - привязка lvalues-rvalue , но, если там ответили, мои извинения, я не смог бы это выяснить.) с любой строкой, и она просто работает.Достаточно определить void barR(const string &x), но мне бы очень хотелось понять, почему.

Большое спасибо за любую помощь в понимании, почему третий вызов отличается.

Ответы [ 2 ]

17 голосов
/ 13 января 2012

Назначение опорных параметров r-значения состоит в том, чтобы конкретно определить, когда объект является r-значением.Потому что если объект является r-значением, то функция знает, что его больше не использовать, поэтому она может делать с ним все, что захочет.Если значение l может связываться со ссылкой на значение r, это означает, что обнаружение, о котором я говорил, на самом деле не происходит.

Если вы хотите передать значение l одной из этих функций, вам нужно использовать std::move.Передача объекта через std::move в функцию, которая получает ссылку на r-значение, все равно что сказать: «Вот, возьми этот объект, вырви его внутренности, мне все равно, что с ним будет».Для ваших целей правильный ответ - указать параметр const.Значение r совершенно счастлив, будучи привязанным к константной ссылке.За исключением конструкторов перемещения, создание эталонных параметров r-значения почти никогда не будет правильным.

5 голосов
/ 13 января 2012

Вам нужно использовать std::move. Это прекрасно работает:

bar(std::move(aardvark));
...