On Friday, 19 February 2016 at 01:30:13 UTC, H. S. Teoh wrote:
Suppose the array gets moved sometime after i=500 because it
ran out of space in the current memory location. Since there
is another slice middleSlice pointing at the old data, it's not
just a matter of *moving* the elements over to the new
location; they have to be *copied* over so that there are now
two copies of the original elements -- the GC doesn't know
whether func may try to access the original elements through
middleSlice, so it cannot just move them. Only when middleSlice
goes out of scope, can the old elements be destructed.
So we see that when an array is grown, the elements cannot
simply be moved to the new location; we must make copies of
them, otherwise any slice of the old data will become invalid.
So after an array is moved, there will be two copies of data,
and if the original elements are unreferenced after all, the GC
will call the dtors when it runs the next collection cycle.
Then when the new elements become unreferenced, the dtors will
be called again at the following collection cycle, on the new
copies of the elements.
So it seems that the conclusion is that it is indeed unsafe to
store non-copyable objects in an array which might grow (though
it would be nice if attempting to do so was a compiler error,
like it is with std.container.Array). I've starting creating a
custom "Vector" type with value semantics which is move-aware, so
hopefully that will address my needs.
Thanks for all the help, folks!