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!

Reply via email to