Is it safe and well-defined for the second argument to std::getline(std::istream&, std::string&)
to be an lvalue referring to a moved-from std::string
, and, if so, is that string restored from its moved-from state, so methods such as pop_back()
can be safely invoked?
Put more simply, does writing to a string with getline()
have equivalent semantics to assigning to that string?
Or more concretely, is the following (somewhat contrived) snippet well-defined and correct?
std::ifstream f("foo.txt");
std::vector<std::string> lines;
for (std::string s; std::getline(f, s); lines.push_back(std::move(s)))
if (!s.empty() && s.back() == '\r')
s.pop_back();
Optimized (-march=native -O3
) builds of this snippet with g++
and clang++
appear to work as expected, but that is of course no guarantee.
I'd like to know if this is relying only on well-defined behavior according to the semantics of getline()
in the C++11 standard, or, if not, if it's well-defined by a later edition of the standard, or, if not, if it's at least explicitly defined by any/all of the major implementations (G++, Clang++, Visual C++, Intel C++ Compiler).
NB: This is not a duplicate of previous questions asking whether it's safe to assign to a moved-from object (yes, if it's a trivial or STL type) because getline()
is not the assignment operator.
Your code is safe, but only because you are checking if the getline
successfully stored something in s
. If the sentry internal to getline
failed to initialize, then nothing would be assigned to s
and it would be left in the valid-but-unspecified state. As long as getline
succeeds in setting s
to a known state, you're good.
And the very first thing getline
does after successful sentry construction is set s
to a zero size (a known state).
More details below in GManNickG's comment.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With