Tôi nhìn một chút tại mảng động trong D2, và tôi thấy chúng rất khó hiểu. Nó cũng có vẻ như tôi đang giải thích các spec sai .. Làm việc trên một tham chiếu hoặc lát của một mảng động có vẻ rất dễ bị lỗi khi thay đổi mảng ... Hoặc tôi chỉ không hiểu những nguyên tắc cơ bản?Thực hành không tốt để thay đổi mảng động có tham chiếu đến chúng?
Đề cập đến cùng một mảng chỉ chia sẻ các mục thực tế:
auto a = [1];
auto b = a;
assert(&a != &b); // different instance; Doesn't share length
assert(a.ptr == b.ptr); // same items
assert(a == [1]);
assert(a == b);
Khi họ tham khảo cùng một mảng, thay đổi một thay đổi khác:
auto a = [1,2];
auto b = a;
a[1] = 20;
assert(a == [1,20]);
assert(a == b);
Từ spec trên mảng
Để tối đa hóa hiệu quả, thời gian chạy luôn cố gắng thay đổi kích cỡ mảng để tránh thêm sao chép. Nó sẽ luôn luôn làm một bản sao nếu kích thước mới lớn hơn và mảng không được cấp phát qua toán tử mới hoặc hoạt động thay đổi kích thước trước đó .
Vì vậy, thay đổi độ dài không neccesarily phá vỡ các tài liệu tham khảo:
auto a = [1];
auto b = a;
b.length = 2;
assert(b == [1,0]);
assert(a == [1]); // a unchanged even if it refers to the same instance
assert(a.ptr == b.ptr); // but still the same instance
// So updates to one works on the other
a[0] = 10;
assert(a == [10]);
assert(b == [10,0]);
Từ spec trên mảng
Concatenation luôn tạo ra một bản sao của toán hạng của nó, ngay cả khi một trong những toán hạng là mảng có độ dài 0
auto a = [1];
auto b = a;
b ~= 2; // Should make a copy, right..?
assert(a == [1]);
assert(b == [1,2]);
assert(a != b);
assert(a4.ptr == b.ptr); // But it's still the same instance
a[0] = 10;
assert(b == [10,2]); // So changes to a changes b
Nhưng khi các mảng sẽ dẫm lên nhau, các giá trị được sao chép vào một vị trí mới và tham chiếu bị hỏng:
auto a = [1];
auto b = a;
b ~= 2;
assert(a == [1]);
assert(b == [1,2]);
a.length = 2; // Copies values to new memory location to not overwrite b's changes
assert(a.ptr != b.ptr);
Thay đổi chiều dài của cả hai mảng trước khi thực hiện một sự thay đổi mang lại cho kết quả tương tự như trên (tôi sẽ hy vọng điều này đưa ra ở trên):
auto a = [1];
auto b = a;
a.length = 2;
b.length = 2;
a[1] = 2;
assert(a == [1,2]);
assert(b == [1,0]);
assert(a.ptr != b.ptr);
Và tương tự khi thay đổi chiều dài hoặc cancatenating (tôi mong chờ này đưa ra ở trên):
auto a = [1];
auto b = a;
b.length = 2;
a ~= 2;
assert(a == [1,2]);
assert(b == [1,0]);
assert(a.ptr != b.ptr);
Nhưng sau đó lát cũng đi vào hình ảnh, và đột nhiên nó thậm chí còn phức tạp hơn! Các lát có thể bị mồ côi ...
auto a = [1,2,3];
auto b = a;
auto slice = a[1..$]; // [2,3];
slice[0] = 20;
assert(a == [1,20,3]);
assert(a == b);
a.length = 4;
assert(a == [1,20,3,0]);
slice[0] = 200;
assert(b == [1,200,3]); // the reference to b is still valid.
assert(a == [1, 20, 3, 0]); // but the reference to a is now invalid..
b ~= 4;
// Now both references is invalid and the slice is orphan...
// What does the slice modify?
assert(a.ptr != b.ptr);
slice[0] = 2000;
assert(slice == [2000,3]);
assert(a == [1,20,3,0]);
assert(b == [1,200,3,4]);
Vậy ... Thực tiễn không tốt để có nhiều tham chiếu đến cùng một mảng động? Và đi qua lát xung quanh vv? Hay tôi chỉ cần ra khỏi đây, thiếu toàn bộ điểm của mảng động trong D?
Cảm ơn câu trả lời chi tiết, tốt. Tôi cũng đã nghe nói về thuộc tính .capacity cho biết độ dài tối đa mà mảng có thể có trước khi nó cần tái phân bổ. Khi thực hiện "auto b = a", chúng sẽ có tham chiếu khác; & a! = & b, nhưng có vẻ như "is" sử dụng .ptr dưới mui xe để kiểm tra tính bình đẳng tham chiếu. – simendsjo