In his report on the Fall 2017 standards meeting, Herb Sutter has the following example of what the range-based for statement with initializer is simplifying:
{
T thing = f();
for (auto& x : thing.items()) {
// Note: “for (auto& x : f().items())” is WRONG
mutate(&x);
log(x);
}
}
Why is for (auto& x : f().items()) wrong? That is, when does f().items() yield undefined behavior but T thing = f(); ... thing.items() not yield it?
(This question might be considered a duplicate but the answer was only revealed by writing the question, not by normal search, so I decided it was worthwhile including in StackOverflow.)
If t.items() returns a reference to a member of t, then f().items() will give you a dangling reference and thus undefined behavior.
Breaking it down: f() will be a temporary that will be destroyed after the items() call returns. If items() returns a reference to a member of that temporary, it will become dangling once the temporary is destroyed.
See https://stackoverflow.com/a/40955021/309334 for more detail and a way of writing your methods so they won't have this problem.
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