2013-09-30 11 views
29

Trong C++ 11 std::array được định nghĩa là có lưu trữ và hiệu suất liền kề không tệ hơn mảng, nhưng tôi không thể quyết định xem các yêu cầu khác nhau của tiêu chuẩn có ngụ ý hay không std :: array có cùng kích thước và bố trí bộ nhớ như một mảng bình thường. Bạn có thể đếm số sizeof(std::array<int,N>) == sizeof(int)*N hoặc triển khai cụ thể không?Là kích thước của std :: mảng được xác định theo tiêu chuẩn

Đặc biệt, là đảm bảo này để làm việc theo cách bạn mong chờ nó:

std::vector< std::array<int, N> > x(M); 
typedef (*ArrayPointer)[N]; 
ArrayPointer y = (ArrayPointer) &x[0][0]; 
// use y like normal multidimensional array 

Nó hoạt động trong hai trình biên dịch tôi đã cố gắng (GNU & Intel). Hơn nữa, tất cả tài liệu của bên thứ 3 tôi có thể tìm thấy (like this), nói rằng std :: array chỉ là bộ nhớ hiệu quả như một mảng đơn giản, kết hợp với yêu cầu liền kề sẽ ngụ ý rằng nó phải có bố cục bộ nhớ giống nhau. Tuy nhiên tôi không thể tìm thấy yêu cầu này trong tiêu chuẩn.

+1

Không có sự bảo đảm như vậy trong 'mảng mẫu lớp 23.3.2', và thực sự, tìm kiếm tiêu chuẩn cho' sizeof' dường như chỉ bật các đảm bảo sau cho tôi: 'char' và các biến thể của nó là' 1', và 'nullptr' có cùng kích thước với' void * '. – us2012

+0

Như @ US2012 nêu rõ, không có bảo đảm rõ ràng. Mặc dù nó có thể hoạt động trên nền tảng lựa chọn của bạn, nhưng nó có thể thất bại trên các nền tảng khác với các ràng buộc căn chỉnh khác nhau. –

Trả lời

23

Đó là gần bắt buộc. Cụ thể, §23.3.2.1/2 nói:

Một mảng là một tổng hợp (8.5.1) có thể được khởi tạo với cú pháp

array<T, N> a = { initializer-list }; 

nơi initializer-list là một dấu phẩy- danh sách được phân tách tối đa N thành phần có loại chuyển đổi thành T.

Vì nó là tổng hợp nên không thể sử dụng bất kỳ loại hàm tạo nào để chuyển đổi dữ liệu trong initializer-list đến đúng định dạng. Điều đó thực sự chỉ để lại một khả năng: về điều duy nhất nó có thể lưu trữ là những giá trị bản thân.

Tôi cho rằng nó sẽ có thể cho một std::array để lưu trữ một số loại dữ liệu phụ trợ sau khi số liệu cụ thể, chẳng hạn như bộ nhớ thêm thiết lập để một số giá trị được xác định trước, vì vậy nếu bạn viết quá khứ cuối mảng, bạn' d có thể thay đổi dữ liệu đó. Trình biên dịch/thời gian chạy sau đó sẽ kiểm tra các giá trị đó khi tắt và nếu bạn đã thay đổi các giá trị, hãy báo cáo hành vi không xác định của mã của bạn.

Cũng có thể trình biên dịch có thể làm đệm/căn chỉnh khác nhau cho một std::array so với mảng được tích hợp sẵn. Một ví dụ rõ ràng mà điều này thậm chí có thể được mong muốn là hỗ trợ các yêu cầu siêu liên kết, chẳng hạn như dữ liệu để sử dụng với các chỉ lệnh SSE của Intel. Mảng tích hợp không thể hỗ trợ siêu liên kết, nhưng tôi nghĩ rằng đặc điểm kỹ thuật của std::array có thể khó đủ để cho phép.

Điểm mấu chốt: không đưa ra câu hỏi về số lượng khả năng có thể tồn tại, rõ ràng là std::array không nhất thiết phải tuân theo quy tắc bạn đang yêu cầu.

+2

Tôi nghĩ rằng nó cũng có thể có đệm, ngay cả khi bắt đầu, vì nó không bắt buộc phải là một lớp bố cục tiêu chuẩn (và không thể, đối với các thành viên của nó có thể thuộc kiểu bố cục không chuẩn). – dyp

+1

[Ví dụ trực tiếp] (http://coliru.stacked-crooked.com/a/34cc30147f6c92c4) (Có, điều này không chứng minh được gì. Tôi đã tìm kiếm cẩn thận Tiêu chuẩn và không tìm thấy bất kỳ yêu cầu * bố cục * nào cho tập hợp hoặc các loại chữ, chỉ dành cho các kiểu bố cục chuẩn, trước đây POD có các yêu cầu này trong C++ 03.) – dyp

+0

C cấm cấu trúc có đệm không tên lúc đầu của chúng trong 6.7.2.1/15 "Có thể có đệm không tên trong một đối tượng cấu trúc, nhưng không phải lúc ban đầu. " (tức là bạn vẫn có thể có nó ở cuối) – dyp

Các vấn đề liên quan