5

免责声明:这个问题是为了理解。我会boost::lexical_cast在现场使用。不过,它已经在现实世界的某些地方出现了。


对“内联” lex-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;
}

结果类似于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;
}

结果是"0hi"

这主要是有道理的,因为operator<<that是 base †††int的成员函数,因此可以在临时调用。该操作的结果是对基址的引用,下一个链接到该基址,即将其读取为.ostreamostreamoperator<<(std::ostringstream() << 0) << "hi"

但是为什么那个操作"hi"会继续产生预期的结果呢?LHS上的参考不是还是暂时的吗?


让我们关注C++03;有人告诉我,由于右值的全能运算符,第一个示例实际上可能在 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);

4

2 回答 2

3

原因很简单。如果您阅读我提出的问题:

std::ostringstream 打印 c 字符串的地址而不是其内容。

您会注意到,获取“正确”引用而不是临时引用的技巧是调用对象上的方法(由于某种原因不限于非绑定限制),该方法将返回引用。

在上面 Nawaz 的回答中,他打电话给std::ostream& std::ostream::flush(),在你的情况下:

std::ostringstream() << 0 << "hi"

你打电话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
}

编辑:但为什么不X&(的结果ref)对待相同?

这是一个分类问题。临时是 aprvalue而参考是 a lvalue。引用只允许绑定到lvalue.

当然,由于可以调用方法rvalue(因此prvalue)并且这些方法可能返回对它们被调用的对象的引用,我们可以轻松绕过愚蠢的(1)引用只允许绑定到lvalue限制......

rvalue(1) 这也与 a可以绑定到 const-reference的事实不一致。

于 2013-01-18T18:34:21.047 回答
2

LHS上的参考不是还是暂时的吗?

它是对临时(返回值)的左值引用,它仍然是左值,因此可以绑定到左值引用。

根据生命周期而不是 l/rvalueness 考虑临时变量。

于 2013-01-18T07:06:20.253 回答