免责声明:这个问题是为了解.我将boost::lexical_cast在现场使用.它已经有点想出了在现实世界中的地方,虽然.
#include <string>
#include <sstream>
#include <iostream>
int main()
{
const std::string s = static_cast<std::ostringstream&>(
std::ostringstream() << "hi" << 0
).str();
std::cout << s;
}
Run Code Online (Sandbox Code Playgroud)
结果是这样的0x804947c0,因为operator<<它的作用"hi"是一个自由函数,其LHS必须采用std::ostream&†,而临时std::ostringstream()不能绑定到ref-to-non const.唯一剩下的比赛是operator<<这需要const void*在RHS ††.
现在让我们交换操作数:
#include <string>
#include <sstream>
#include <iostream>
int main()
{
const std::string s = static_cast<std::ostringstream&>(
std::ostringstream() << 0 << "hi"
).str();
std::cout << s;
}
Run Code Online (Sandbox Code Playgroud)
结果是"0hi".
这通常是有道理的,因为所operator<<需要的int是基础ostream†††的成员函数,因此,在临时调用时很好.该操作的结果是对ostream基数的引用,下一个operator<<链接到该基数,即将其读取为(std::ostringstream() << 0) << "hi".
但是为什么这样的操作"hi"会继续产生预期的结果呢?LHS上的参考还不是暂时的吗?
让我们专注于C++ 03; 我被告知,由于rvalues的catch-all运算符,第一个例子实际上可能在C++ 11中作为"预期"工作.
† [C++03: 27.6.2.1]: template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);
†† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);
††† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);
原因很简单。如果您阅读了我提出的问题:
您会注意到,获取“正确”引用而不是临时引用的技巧是调用对象上的方法(由于某种原因不限于非绑定限制),该方法将返回引用。
在上面纳瓦兹的回答中,他打电话给std::ostream& std::ostream::flush(),就你的情况而言:
std::ostringstream() << 0 << "hi"
Run Code Online (Sandbox Code Playgroud)
你打电话std::ostringstream& std::ostringstream::operator<<(int)。
相同的结果。
令人惊讶的行为是由于ostream混杂实现造成的:一些operator<<是成员方法,而另一些是自由函数。
X& ref()您可以简单地通过在对象上实现方法来测试它:
struct X { X& ref(); };
void call(X& x);
int main() {
call(X{}); // error: cannot bind X& to a temporary
call(X{}.ref()); // OK
}
Run Code Online (Sandbox Code Playgroud)
编辑:但为什么X&(的结果ref)不被同等对待?
这是一个分类问题。临时的是 a prvalue,而引用是 a lvalue。引用只允许绑定到lvalue.
当然,由于可以调用方法rvalue(因此prvalue),并且这些方法可能返回对它们被调用的对象的引用,我们可以轻松绕过愚蠢的(1)引用只允许绑定到lvalue限制...
rvalue(1) 这也与 a可以绑定到 const 引用的事实不一致。
| 归档时间: |
|
| 查看次数: |
181 次 |
| 最近记录: |