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 右值引用 - 左值-右值绑定, 但是,如果在那里得到答案,我很抱歉,我无法将其提炼出来。
我想要的是能够使用任何类型的字符串调用我的函数 bar() 并让它正常工作。定义 void barR(const string &x)
就足够了,但我真的很想理解为什么。
非常感谢您帮助理解为什么第三次通话不同。
I have three function calls that I think should be treated (about) the same, but clearly they are not. I'm trying to understand why one of three doesn't compile (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&&)’
*/
}
This question is a bit along the lines of
C++0x rvalue references - lvalues-rvalue binding,
but, if it's answered there, my apologies, I wasn't able to distil it out.
What I want is to be able to call my function bar() with any sort of string and have it just work. It's enough to define void barR(const string &x)
, but I'd really like to understand why.
Thanks much for any help in understanding why the third call is different.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
右值引用参数的目的是专门检测对象何时为右值。因为如果一个对象是右值,那么函数就知道它不会被再次使用,所以它可以用它做任何它想做的事情。如果左值可以绑定到右值引用,则意味着我正在讨论的检测实际上并未发生。
如果要将左值传递给这些函数之一,则需要使用
std::move
。通过std::move
将对象传递给采用右值引用的函数就像是在说:“在这里,拿走这个对象,撕掉它的内脏,我不在乎它会发生什么”。出于您的目的,正确的答案是将参数设置为常量引用。 r 值非常乐意绑定到 const 引用。除了移动构造函数之外,创建右值引用参数几乎从来都不是正确的做法。
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 viastd::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.
您需要使用
std::move
。这工作正常:You need to use
std::move
. This works fine :