std :: dynarray vs std :: vector


84

C ++ 14 trình bày std::dynarray:

std :: dynarray là một vùng chứa trình tự đóng gói các mảng với kích thước được cố định khi xây dựng và không thay đổi trong suốt thời gian tồn tại của đối tượng.

std::dynarrayphải được phân bổ trong thời gian chạy giống như std::vector.

Vì vậy, những lợi ích và cách sử dụng std::dynarraywhile chúng ta có thể sử dụng std::vectorcái nào năng động hơn (và cũng khá lớn)?


1
Này, từ khi nào "C ++ 14" là một thẻ? Tôi đang tìm kiếm rằng ngày khác và nó không tồn tại ...
Kerrek SB

1
Được std::valarrayđổi tên thành std::dynarray? Có gì động std::dynarraykhi không thể thay đổi kích thước?
yasouser

9
@yasouser, không, không liên quan gì cả valarray. Đó là năng động bởi vì độ dài của mảng là một giá trị thời gian chạy, nó không cần phải được biết đến tại thời gian biên dịch, không giống nhưstd::array
Jonathan Wakely

21
Lưu ý rằng tại cuộc họp của Ủy ban Tiêu chuẩn C ++ vào tuần trước, dynarrayđã được xóa khỏi C ++ 14 và đưa vào Đặc tả kỹ thuật trong tương lai (hãy coi đó là phiên bản mới của TR1) vì nó có một số vấn đề kỹ thuật nghiêm trọng.
Pete Becker

2
dynarray không còn là một phần của dự thảo C ++ 14
cassinaj

Câu trả lời:


89

Vì vậy, những lợi ích và cách sử dụng std::dynarray, khi chúng ta có thể sử dụng std::vectornăng động hơn (Re-sizable)?

dynarraynhỏ hơn và đơn giản hơn vector, bởi vì nó không cần quản lý các giá trị kích thước và dung lượng riêng biệt cũng như không cần lưu trữ một bộ cấp phát.

Tuy nhiên, lợi ích hiệu suất chính được dự định đến từ thực tế là các triển khai được khuyến khích phân bổ dynarraytrên ngăn xếp khi có thể, tránh bất kỳ phân bổ heap nào. ví dụ

std::dynarray<int> d(5);   // can use stack memory for elements
auto p = new std::dynarray<int>(6);  // must use heap memory for elements

Việc tối ưu hóa này yêu cầu sự hợp tác từ trình biên dịch, nó không thể được triển khai như một loại thư viện thuần túy và phép thuật trình biên dịch cần thiết đã không được thực hiện và không ai chắc chắn rằng nó dễ dàng như thế nào. Vì thiếu kinh nghiệm triển khai, tại cuộc họp ủy ban C ++ ở Chicago tuần trước, họ đã quyết định rút std::dynarraykhỏi C ++ 14 và phát hành tài liệu TS (đặc tả kỹ thuật) mở rộng mảng riêng biệt để xác định std::experimental::dynarrayvà các mảng ràng buộc thời gian chạy (ARB, tương tự sang C99 VLA.) Điều này std::dynarraygần như chắc chắn sẽ không có trong C ++ 14.


1
Tuyệt vời, tôi đã tự hỏi liệu có bất kỳ triển khai không tầm thường nào dynarraytrong tự nhiên không. Tôi luôn nghĩ rằng bạn cần hai triển khai độc lập của thực tiễn hiện có trước khi một thứ gì đó đủ điều kiện để tiêu chuẩn hóa.
Kerrek SB

Không, không có cách triển khai nào của phân bổ ngăn xếp dynarray. Mặc dù kinh nghiệm thực hiện là rất hữu ích, không có quy tắc thiết lập đòi hỏi nó (nhưng một số sẽ nói nên có!)
Jonathan Wakely

động não ở đây thôi chứ còn tạo 2 hàm: std :: dynarray make_dyn_autostorage (int) và std :: dynarray make_dyn_heap (int) thì sao?
Phục vụ Laurijssen

2
@KerrekSB, vâng, chuyển động thư viện 10 ở Chicago là: "Di chuyển chúng tôi tạo Giấy làm việc cho Phần mở rộng mảng theo kế hoạch TS, loại bỏ các chỉnh sửa được áp dụng cho CD C ++ 14 bởi hai giấy N3639 ," Mảng có kích thước thời gian chạy với tự động thời lượng lưu trữ (bản sửa đổi 5) " N3662 ," Mảng động C ++ (dynarray) "và chỉ đạo trình soạn thảo dự án Phần mở rộng mảng TS áp dụng những từ đó vào Giấy làm việc của Phần mở rộng mảng làm nội dung ban đầu của nó."
Jonathan Wakely

3
@ h9uest không liên quan gì đến "những người C ++", đó là tên chính thức của các sản phẩm của ủy ban kỹ thuật ISO , xem iso.org/iso/home/standards_development/…iso.org/iso/home/standards_development /…
Jonathan Wakely

31

Như bạn đã nói, std::dynarraylà dành cho một mảng động có kích thước cố định . Nó không thể thay đổi kích thước. Đại khái nó đang nói một sự cải tiến hơn new T[N]và hơn std::unique_ptr<T[]>(new T[N]).

Không cần thay đổi kích thước hoặc quản lý dung lượng có nghĩa là bạn có thể triển khai cấu trúc dữ liệu với ít phức tạp hơn và tốn ít dung lượng hơn.

Hơn nữa, std::dynarraylà một động vật kỳ lạ cho phép triển khai thực hiện nó theo những cách khác nhau, không cụ thể, ví dụ: có thể đặt mảng trên ngăn xếp. Gọi một hàm phân bổ là "tùy chọn". Bạn có thể chỉ định một bộ cấp phát để xây dựng các phần tử của mảng, nhưng đó không phải là một phần của kiểu.

Bạn cũng có thể thắc mắc tại sao chúng ta cần std::dynarray các mảng có độ dài thay đổi. VLA trong C ++ 14 hạn chế hơn nhiều; chúng chỉ có thể là biến cục bộ, biến tự động và không cung cấp cách nào để chỉ định chính sách phân bổ và tất nhiên chúng không có giao diện vùng chứa chuẩn.


Một số ví dụ từ 23.3.4.2 của "bản nháp hiện tại" (lấy đó là bộ nhớ cache của Google):

explicit dynarray(size_type c);

Hiệu ứng: Phân bổ bộ nhớ cho ccác phần tử. Có thể hoặc không thể gọi toàn cầu operator new.

template <class Alloc>
dynarray(size_type c, const Alloc& alloc);

Hiệu ứng: Tương đương với các hàm tạo trước đó ngoại trừ mỗi phần tử được xây dựng bằng cấu trúc phân bổ sử dụng .

Việc bạn có thể sử dụng một bộ cấp phát nhất định để xây dựng các phần tử mảng hay không là một đặc điểm chung:

cấu trúc mẫu using_allocator, Alloc>: true_type {};

Yêu cầu: Alloc phải là Bộ phân bổ (17.6.3.5). [ Lưu ý: Việc chuyên biệt hóa đặc điểm này thông báo cho các thành phần thư viện khác dynarraycó thể được xây dựng bằng bộ cấp phát, mặc dù nó không có kiểu cấp phát lồng nhau.]

Chỉnh sửa: Câu trả lời của Jonathan Wakely chắc chắn sẽ có thẩm quyền và sâu sắc hơn nhiều.


Việc chuyển một hàm cấp phát tới hàm tạo dynarraycủa phần tử không bao giờ được sử dụng để cấp phát, nó chỉ được sử dụng như một đối số cho các hàm tạo của phần tử (sử dụng "cấu trúc hàm phân bổ use"). Đó là lý do tại sao bạn không thể truy vấn nếu trình cấp phát đã được sử dụng: bởi vì nó không bao giờ được sử dụng.
Jonathan Wakely

@JonathanWakely: À, tôi đã hiểu lầm điều đó. Cảm ơn, đã sửa!
Kerrek SB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.