Путаница связывания значений в C++
У меня есть три вызова функций, которые, по моему мнению, должны рассматриваться (примерно) одинаково, но, очевидно, это не так. Я пытаюсь понять, почему один из трех не компилируется (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, но, если на него есть ответ, мои извинения, я не смог его отфильтровать.
Я хочу иметь возможность вызывать мою функцию bar() с любой строкой, чтобы она работала. Достаточно определить void barR(const string &x)
, но я бы очень хотел понять почему.
Большое спасибо за любую помощь в понимании, почему третий звонок отличается.
2 ответа
Назначение опорных параметров r-значения состоит в том, чтобы конкретно определять, когда объект является r-значением. Потому что если объект является r-значением, то функция знает, что его больше не использовать, поэтому она может делать с ним все, что захочет. Если бы значение l могло связываться со ссылкой на значение r, это означало бы, что обнаружение, о котором я говорил, на самом деле не происходило.
Если вы хотите передать l-значение одной из этих функций, вам нужно использовать std::move
, Передача объекта через std::move
для функции, которая принимает ссылку на r-значение, все равно, что сказать: "Вот, возьми этот объект, вырви его изнутри, мне все равно, что с ним будет".
Для ваших целей правильный ответ - указать параметр const. Значение r совершенно счастлив, будучи привязанным к константной ссылке. За исключением конструкторов перемещения, создание ссылочных параметров r-значения почти никогда не будет правильным.
Вам нужно использовать std::move
, Это отлично работает:
bar(std::move(aardvark));