On Tuesday, September 13, 2016 15:27:07 Neurone via Digitalmars-d-learn wrote: > On Sunday, 11 September 2016 at 16:14:59 UTC, Mike Parker wrote: > > On Sunday, 11 September 2016 at 16:10:04 UTC, Mike Parker wrote: > >> And here, no memory is allocated. barSlice.ptr is the same as > >> bar.ptr and barSlice.length is the same as bar.length. > >> However, if you append a new element: > >> > >> barSlice ~= 10; > >> > >> The GC will allocate memory for a new array and barSlice will > >> no longer point to bar. It will now have four elements. > > > > I should clarify that this holds true for all slices, not just > > slices of static arrays. The key point is that appending to a > > slice will only allocate if the the .capacity property of the > > slice is 0. Slices of static arrays will always have a capacity > > of 0. Slices of slices might not, i.e. there may be room in the > > memory block for more elements. > > Thanks for the detailed answer. I still don't get the advantage > of passing slices into functions by value allowing modification > to elements of the original array. Is there an way to specify > that a true independent copy of an array should be passed into > the function? E.g, in c++ func(Vector<int> v) causes a copy of > the argument to be passed in.
Slices are a huge performance boost (e.g. the fact that we have slicing like this for strings makes parsing code _way_ more efficient by default than would ever be the case for something like std::string). If you're worried about a function mutating the elements of an array that it's given, then you can always mark them with const. e.g. auto foo(const(int)[] arr) {...} But there is no way to force a naked dynamic array to do a deeper copy when passed. If you're worried about it, you can explicitly call dup to create a copy of the array rather than slice it - e.g. foo(arr.dup) - but the function itself can't enforce that behavior. The closest that it could do would be to explicitly dup the parameter itself - though if you were going to do that, you'd want to make it clear in the documentation, since that's not a typical thing to do, and if someone wanted to ensure that an array that they were passing to the function didn't get mutated, they'd dup it themselves, which would result in two dups if your function did the dup. If you want a dynamic array to be duped every time it's passed to a function or otherwise copied, you'd need to create a wrapper struct with a postblit constructor that called dup. That would generally make for unnecessarily inefficient code though. The few containers in std.container are all reference types for the same reason - containers which copy by default make it way too easy to accidentally copy them and are arguably a bad default (though obviously, there are cases where that would be the best behavior). So, the typical thing to do with dynamic arrays is to use const or immutable elements when you want to ensure that they don't get mutated when passing them around and duping or iduping a dynamic array when you want to ensure that you have a copy of the array rather than a slice. - Jonathan M Davis