为什么`operator<<`for“basic_ostream”的rvalue重载返回左值引用?

时间:2012-01-12 01:20:04

标签: c++ c++11 iostream rvalue-reference

§27.7.3.9operator<<定义了以下重载:

template <class charT, class traits, class T>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>&& os, const T& x);
  

效果: os << x
  返回: os

§27.7.2.6定义operator>>的右值超载。)
基本上,它只是转发到左值超载。我认为这个重载非常危险(实际上istream甚至比ostream更重要),请考虑以下内容:

#include <sstream>
#include <iostream>

int main(){
  auto& s = (std::stringstream() << "hi there!\n");
  std::cout << s.rdbuf(); // oops
}

Live example on Ideone(未定义行为的完美示例。在MSVC10上没有为我打印)。

上面的示例可能看起来很人为,但是在通用代码中或者将(std::stringstream() << "text")传递给提供左值和右值超载并存储{的函数时,不应该太难以进入这种情况。 {1}}或std::ostream根据过载以不同的方式。

现在,再次返回std::istream并指定以下内容的参数是什么?

  

返回: move(os)

basic_ostream<charT, traits>&&也一样。)

有什么我可以忽略的吗?在目前的状态,在我看来,它看起来很危险,就像一个缺陷。我浏览了LWG issue list并找到了this proposal(hi @HowardHinnant!)。它确实返回了一个rvalue,但这只是为了能够链接这个特殊的运算符,而不是专门解决我上面描述的安全问题(虽然肯定 解决它)。此外,它被标记为关闭并重新考虑下一个标准。因此,我想我会在这里问:

为什么上面提到的重载返回左值引用有充分的理由吗?

1 个答案:

答案 0 :(得分:15)

这是一个缺陷,这是我的错,抱歉。 LWG 1203(感谢为我找到!:-))是我目前对&#34; rvalue-stream-inserter&#34;的正确解决方案的看法。请注意,你仍然可以抓住它并遇到麻烦:

auto&& s = (std::stringstream() << "hi there!\n");
std::cout << s.rdbuf(); // oops

虽然至少在上面的代码中,你可以做一些你不应该做的事情(因为&&)更为明显。

相关问题