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

时间:2013-01-18 07:01:01

标签: c++

免责声明:此问题仅供参考。我将在该字段中使用boost::lexical_castIt has sort of come up in the real world in places, though.


以{inline“lex-cast方法取the following attempt

#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<<,它在RHS ††上取const void*

现在let's swap the operands

#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<< 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);

2 个答案:

答案 0 :(得分:3)

原因很简单。如果你读到我问过的问题:

  

std::ostringstream printing the address of the c-string instead of its content.

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

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

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

你致电std::ostringstream& std::ostringstream::operator<<(int)

同样的结果。

令人惊讶的行为是由于ostream mishmash实现:一些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的结果)处理相同的内容?

这是classification的问题。临时是prvalue,而引用是lvalue。引用仅允许绑定到lvalue

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

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

答案 1 :(得分:2)

  

LHS的参考资料是否仍然是暂时的?

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

从终身而不是l / rvalueness的角度考虑临时性。