Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
369 views
in Technique[技术] by (71.8m points)

c++ - Why does the rvalue overload of `operator<<` for `basic_ostream` return an lvalue reference?

§27.7.3.9 defines the following overload for operator<<:

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

Effects: os << x
Returns: os

(§27.7.2.6 defines the rvalue overload for operator>>.)
Basically, it just forwards to an lvalue overload. I consider this overload to be pretty dangerous (the istream one even more so than the ostream one, actually), consider the following:

#include <sstream>
#include <iostream>

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

Live example on Ideone (perfect example of undefined behaviour. Prints nothing for me on MSVC10).

The above example might look contrived, but it shouldn't be too hard to get into this situation in generic code or when passing the (std::stringstream() << "text") to a function that provides an lvalue and an rvalue overload and stores the std::ostream or std::istream in different ways according to the overload.

Now, what would be an argument agains returning a basic_ostream<charT, traits>&& and specifying the following?

Returns: move(os)

(And the same for basic_istream.)

Is there anything I'm overlooking? At the current state, in my eyes, it just looks dangerous and like a defect. I skimmed through the LWG issue list and found this proposal (hi @HowardHinnant!). It indeed returns an rvalue, however only for the added benefit of being able to chain this special operator, not specifically addressing the safety issue I described above (though it certainly does solve it). Additionally, it's marked as closed and for reconsideration for the next standard. As such, I thought I'd ask here:

Is there any good reason why the above mentioned overload returns an lvalue reference?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It's a defect and it is my fault, sorry. LWG 1203 (thanks for finding that for me! :-)) is my current opinion of the correct fix for the "rvalue-stream-inserter". Note though that you could still catch it and be in trouble:

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

Though at least in the above code it is a little more obvious (because of the &&) that you're doing something you shouldn't.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...