You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[spec/arrays] Improve capacity docs
Signed-off-by: Dennis <dkorpel@users.noreply.github.com>
Merged-on-behalf-of: Dennis <dkorpel@users.noreply.github.com>
Copy file name to clipboardExpand all lines: spec/arrays.dd
+70-11Lines changed: 70 additions & 11 deletions
Original file line number
Diff line number
Diff line change
@@ -576,8 +576,6 @@ Returns an array literal with each element of the literal being the $(D .init) p
576
576
the number of bytes per array element.)
577
577
$(TROW $(D .length), Returns the number of elements in the array.
578
578
This is a fixed quantity for static arrays. It is of type $(D size_t).)
579
-
$(TROW $(D .capacity), Returns the number of elements that can be appended to the array without reallocating.
580
-
$(D .capacity) is always $(D 0) for static arrays because their size cannot be modified.)
581
579
$(TROW $(D .ptr), Returns a pointer to the first element of the array.)
582
580
$(TROW $(D .dup), Create a dynamic array of the same size and copy the contents of the array into it. The copy will have any immutability or const stripped. If this conversion is invalid the call will not compile.)
583
581
$(TROW $(D .idup), Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. If this conversion is invalid the call will not compile.)
@@ -607,7 +605,8 @@ Returns an array literal with each element of the literal being the $(D .init) p
607
605
which is 8 in 32-bit builds and 16 on 64-bit builds.))
608
606
$(TROW $(D .length), Get/set number of elements in the
609
607
array. It is of type $(D size_t).)
610
-
$(TROW $(D .capacity), Returns the number of elements that can be appended to the array without reallocating.)
608
+
$(TROW $(D .capacity), Returns the number of elements that can be appended to the array without reallocating.
609
+
See $(RELATIVE_LINK2 capacity-reserve, here) for details.)
611
610
$(TROW $(D .ptr), Returns a pointer to the first element of the array.)
612
611
$(TROW $(D .dup), Create a dynamic array of the same size and copy the contents of the array into it. The copy will have any immutability or const stripped. If this conversion is invalid the call will not compile.)
613
612
$(TROW $(D .idup), Create a dynamic array of the same size and copy the contents of the array into it. The copy is typed as being immutable. If this conversion is invalid the call will not compile.)
@@ -664,7 +663,7 @@ $(H4 $(LNAME2 growing, Growing an Array))
664
663
is larger and either:)
665
664
666
665
* The array was not $(DDSUBLINK spec/garbage, op_involving_gc, allocated by the GC).
667
-
* There is no spare $(RELATIVE_LINK2 capacity-reserve, capacity) in the array.
666
+
* There is no spare $(RELATIVE_LINK2 capacity-reserve, capacity) for the array.
668
667
* Resizing in place would overwrite valid data still accessible in another slice.
669
668
670
669
$(SPEC_RUNNABLE_EXAMPLE_RUN
@@ -759,24 +758,84 @@ array.length = i;
759
758
760
759
$(H3 $(LNAME2 capacity-reserve, `capacity` and `reserve`))
761
760
762
-
$(P The $(D capacity) property gives the maximum length the array
763
-
can grow to without reallocating. The spare capacity for array *a*
764
-
is `a.capacity - a.length`.)
761
+
$(P The $(D capacity) property gives the maximum length a dynamic array
762
+
can grow to without reallocating. If the array does not point to
763
+
GC-allocated memory, the capacity will be zero.
764
+
The spare capacity for an array *a* is `a.capacity - a.length`.)
765
+
766
+
$(P By default, `capacity` will be zero if an element has been stored after the slice.)
767
+
768
+
$(SPEC_RUNNABLE_EXAMPLE_RUN
769
+
---
770
+
int[] a;
771
+
assert(a.capacity == 0);
772
+
a.length = 3; // may allocate spare capacity too
773
+
assert(a.capacity >= 3);
774
+
auto b = a[1..3];
775
+
assert(b.capacity >= 2); // either a or b can append into any spare capacity
776
+
b = a[0..2];
777
+
assert(b.capacity == 0);
778
+
---
779
+
)
780
+
781
+
$(RATIONALE This behaviour helps prevent accidental overwriting of
782
+
elements in another slice. It is also necessary to protect immutable
783
+
elements from being overwritten.)
784
+
765
785
$(P The $(D reserve)
766
-
function expands an array's capacity for use by the append operator.)
786
+
function expands an array's capacity for use by the
787
+
$(RELATIVE_LINK2 array-appending, append operator) or `.length` assignment.)
767
788
768
-
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
789
+
$(SPEC_RUNNABLE_EXAMPLE_RUN
769
790
---------
770
791
int[] array;
771
-
size_t cap = array.reserve(10); // request
792
+
const size_t cap = array.reserve(10); // request
772
793
assert(cap >= 10); // allocated may be more than request
794
+
assert(array.ptr != null);
773
795
774
796
int[] copy = array;
797
+
assert(copy.capacity == cap); // array and copy have same capacity
775
798
array ~= [1, 2, 3, 4, 5]; // grow in place
776
-
assert(cap == array.capacity);
799
+
assert(cap == array.capacity); // array memory was not reallocated
777
800
assert(copy.ptr == array.ptr);
801
+
assert(copy.capacity == 0);
802
+
copy ~= 0; // new allocation
803
+
assert(copy.ptr != array.ptr);
778
804
---------
779
805
)
806
+
$(P Above, `copy`'s length remains zero but it points to the same
807
+
memory allocated by the `reserve` call. Because `array` is then appended
808
+
to, `copy.ptr + 0` no longer points to unused memory - instead that
809
+
is the address of `array[0]`. So `copy.capacity` will be zero to
810
+
prevent any appending to `copy` from overwriting elements in `array`.)
811
+
812
+
$(NOTE The runtime uses the number of appended elements to track the
813
+
start of the spare capacity for the memory allocation.)
814
+
815
+
$(P When an array with spare capacity has its length reduced, or is
816
+
assigned a slice of itself that ends before the previous last element,
817
+
the capacity will be zero.)
818
+
819
+
$(P The `@system` function $(REF1 assumeSafeAppend, object) allows the
820
+
capacity to be regained, but care must be taken not to overwrite
821
+
immutable elements that may exist in a longer slice.)
822
+
823
+
$(SPEC_RUNNABLE_EXAMPLE_RUN
824
+
---
825
+
int[] a = [1, 2, 3];
826
+
a.length--;
827
+
assert(a.capacity == 0);
828
+
a.assumeSafeAppend();
829
+
assert(a.capacity >= 3);
830
+
---
831
+
)
832
+
833
+
$(NOTE Accessing `.capacity` may require the runtime to
834
+
acquire a global lock and perform a cache lookup.)
835
+
836
+
$(BEST_PRACTICE Avoid intensive use of `.capacity` in performance-sensitive code.
837
+
Instead, track the capacity locally when building an array via a unique reference.)
838
+
780
839
781
840
$(H3 $(LNAME2 func-as-property, Functions as Array Properties))
0 commit comments