这是一个对临时的引用到非const绑定的实例吗?

Lig*_*ica 5 c++

免责声明:这个问题是为了解.我将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;
}
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);

Mat*_* M. 3

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

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

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

在上面纳瓦兹的回答中,他打电话给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 引用的事实不一致。