called copy constructor in foreach with ref on Range
Jonathan M Davis
newsgroup.d at jmdavisprog.com
Mon Jun 22 16:25:11 UTC 2020
On Sunday, June 21, 2020 2:25:37 PM MDT kinke via Digitalmars-d-learn wrote:
> A foreach over a custom range makes an initial copy, so that the
> original range is still usable after the foreach (not empty).
No, it's not so that the range will be useable afterwards. In fact, for
generic code, you must _never_ use a range again after passing it to
foreach, because the copying semantics of ranges are not specified, and you
can get radically different behavior depending on what the copying semantics
of a range are (e.g. if it's a class, then it's just copying the reference).
In general, you should never use a range after it's been copied unless you
know exactly what type of range you're dealing with and what its copying
behavior is. If you want an independent copy, you need to use save.
The reason that foreach copies the range is simply due to how the code is
lowered. e.g.
foreach(e; range)
{
}
essentially becomes
for(auto r = range; !r.empty; r.popFront())
{
auto e = r.front;
}
And the fact that a copy is made is likely simply a result of it mimicking
what happens with arrays. Either way, you should never be doing something
like
foreach(e; range)
{
}
auto v = range.front;
in generic code. It needs to be
foreach(e; range.save)
{
}
auto v = range.front;
instead.
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list