8

我认为应该(大约)相同地对待三个函数调用,但显然它们不是。我试图理解为什么三个之一不能编译(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),但我真的很想了解原因。

非常感谢您在理解第三次调用为何不同方面提供的任何帮助。

4

2 回答 2

18

The purpose of r-value reference parameters is to detect specifically when an object is an r-value. Because if an object is an r-value, then the function knows it won't be used again, so it can do whatever it wants with it. If an l-value could bind to an r-value reference, that would mean the detection I was talking about wasn't actually taking place.

If you want to pass an l-value to one of these functions, you need to use std::move. Passing an object via std::move to a function that takes an r-value reference is like saying, "here, take this object, rip it's guts out, I don't care what happens to it".

For your purposes, the correct answer is to make the parameter const reference. An r-value is perfectly happy being bound to a const reference. Except for move constructors, making r-value reference parameters is almost never the correct thing to do.

于 2012-01-13T14:02:34.923 回答
5

你需要使用std::move. 这很好用:

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