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

Xeo*_*Xeo 24 c++ iostream rvalue-reference c++11

§27.7.3.9为以下内容定义以下重载operator<<:

template <class charT, class traits, class T>
  basic_ostream<charT, traits>&
  operator<<(basic_ostream<charT, traits>&& os, const T& x);
Run Code Online (Sandbox Code Playgroud)

效果: os << x
退货: os

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

#include <sstream>
#include <iostream>

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

关于Ideone的实例(未定义行为的完美示例.在MSVC10上没有为我打印).

上面的例子看起来做作,但它不应该太难进入这个情况在通用代码或传递时(std::stringstream() << "text"),以提供一个左值和一个右值过载和存储功能std::ostreamstd::istream以不同的方式根据过载.

现在,又将返回a basic_ostream<charT, traits>&&并指定以下内容的参数是什么?

返回: move(os)

(同样的basic_istream.)

有什么我可以忽略的吗?在目前的状态,在我看来,它看起来很危险,就像一个缺陷.我浏览了LWG问题列表并找到了这个提议(嗨@HowardHinnant!).它确实会返回一个右值,但是只为能够链这个特殊的运营商,而不是专门针对我上面描述的安全问题(尽管它肯定是额外的好处,确实解决它).此外,它被标记为关闭并重新考虑下一个标准.因此,我想我会在这里问:

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

How*_*ant 15

这是一个缺陷,这是我的错,抱歉. LWG 1203(感谢为我找到!:-))是我目前对"rvalue-stream-inserter"正确修复的看法.请注意,你仍然可以抓住它并遇到麻烦:

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

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

  • 嗯..然后..根本不更好地返回没有引用,只是一个`basic_ostream <charT,traits>`被移入?这将禁用lvalue ref绑定,并通过`auto &&`和`auto const&`允许生命周期扩展的正确语义,同时仍然能够像你提议的那样链接该运算符. (2认同)