(我在 comp.std.c++ 上问了这个问题的一个变体,但没有得到答案。)
为什么f(arg)
此代码中的调用调用 const ref 重载f
?
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
我的直觉说f(string &&)
应该选择重载,因为arg
无论如何都需要将其转换为临时值,并且临时值比右值引用更好地匹配右值引用。
这不是在GCC 和MSVC 中发生的(编辑:感谢 Sumant:它不会在 GCC 4.3-4.5 中发生)。至少在G++ 和MSVC 中,任何左值都不会绑定到右值引用参数,即使创建了中间临时值也是如此。实际上,如果不存在 const ref 重载,编译器会诊断出错误。但是,如您所料,编写f(arg + 0)
orf(std::string(arg))
确实选择了右值引用重载。
从我对 C++0x 标准的阅读来看,在考虑是否可行时,似乎应该考虑将 const char * 隐式转换为字符串f(string &&)
,就像传递 const lvalue ref 参数时一样。第 13.3 节(重载解决方案)在太多地方没有区分右值引用和 const 引用。此外,如果存在中间临时对象,阻止左值绑定到右值引用 (13.3.3.1.4/3) 的规则似乎不应该适用——毕竟,从临时对象中移出是完全安全的。
这是:
- 我误读/误解了标准,其中实现的行为是预期的行为,并且有一些很好的理由说明我的示例应该按照它的方式运行?
- 编译器供应商都犯了一个错误?还是基于常见实施策略的错误?或者例如 GCC 中的一个错误(这个左值/右值引用绑定规则是第一次实现的),被其他供应商复制了?
- 标准中的缺陷,或意外后果,或应该澄清的东西?
编辑:我有一个相关的后续问题:C++0x rvalue references - lvalues-rvalue binding