std::array
vượt trội hơn hẳn so với mảng C. Và ngay cả khi tôi muốn tương tác với mã kế thừa, tôi chỉ có thể sử dụng std::array::data()
. Có lý do gì tôi muốn một mảng trường học cũ không?
std::array
vượt trội hơn hẳn so với mảng C. Và ngay cả khi tôi muốn tương tác với mã kế thừa, tôi chỉ có thể sử dụng std::array::data()
. Có lý do gì tôi muốn một mảng trường học cũ không?
Câu trả lời:
Trừ khi tôi đã bỏ lỡ điều gì đó (tôi đã không theo dõi quá kỹ những thay đổi gần đây nhất trong tiêu chuẩn), hầu hết các công dụng của mảng kiểu C vẫn còn. std::array
cho phép khởi tạo tĩnh, nhưng nó vẫn không tính các bộ khởi tạo cho bạn. Và vì việc sử dụng thực sự duy nhất của mảng kiểu C trước đây std::array
là cho các bảng được khởi tạo tĩnh dọc theo các dòng:
MyStruct const table[] =
{
{ something1, otherthing1 },
// ...
};
sử dụng các hàm mẫu begin
và thông thường end
(được sử dụng trong C ++ 11) để lặp lại chúng. Không bao giờ đề cập đến kích thước mà trình biên dịch xác định từ số lượng trình khởi tạo.
CHỈNH SỬA: Một điều khác mà tôi quên mất: chuỗi ký tự vẫn là mảng kiểu C; tức là với loại char[]
. Tôi không nghĩ rằng bất cứ ai sẽ loại trừ việc sử dụng các ký tự chuỗi chỉ vì chúng tôi có std::array
.
const char[]
Không. Nói thẳng ra. Và trong 30 ký tự.
Tất nhiên, bạn cần mảng C để triển khai std::array
, nhưng đó không thực sự là lý do mà người dùng muốn mảng C. Ngoài ra, không, std::array
hiệu suất không kém so với mảng C và có tùy chọn cho quyền truy cập được kiểm tra giới hạn. Và cuối cùng, hoàn toàn hợp lý khi bất kỳ chương trình C ++ nào phụ thuộc vào thư viện Tiêu chuẩn - đó là điểm của nó là Tiêu chuẩn- và nếu bạn không có quyền truy cập vào thư viện Tiêu chuẩn, thì trình biên dịch của bạn không tuân thủ và câu hỏi được gắn thẻ "C ++", không phải "C ++ và những thứ không phải C ++ bỏ sót một nửa thông số kỹ thuật vì họ cảm thấy nó không phù hợp.".
std::array
trong việc triển khai C ++ 11 tự do.
Có vẻ như sử dụng mảng đa chiều dễ dàng hơn với mảng C hơn std::array
. Ví dụ,
char c_arr[5][6][7];
như trái ngược với
std::array<std::array<std::array<char, 7>, 6>, 5> cpp_arr;
Cũng do thuộc tính phân rã tự động của mảng C, c_arr[i]
trong ví dụ trên sẽ phân rã thành một con trỏ và bạn chỉ cần chuyển các kích thước còn lại dưới dạng thêm hai tham số. Quan điểm của tôi là nó c_arr
không đắt tiền để sao chép. Tuy nhiên, cpp_arr[i]
sẽ rất tốn kém để sao chép.
array
cho một hàm mà không làm mất thứ nguyên. Và nếu bạn chuyển nó vào một mẫu hàm, thì hàm đó có thể suy ra cả thứ nguyên và kích thước của mỗi thứ nguyên hoặc chỉ một trong hai thứ nguyên. Điều này có thể thú vị đối với các thư viện mẫu khoa học chủ yếu hoạt động trên các kích thước tùy ý.
template <typename T, int M, int N> using array2d = std::array<std::array<T, N>, M>;
sẽ giải quyết bất kỳ vấn đề nào trong số đó.
c_arr
là rất đắt để sao chép! Bạn phải tự cung cấp mã để làm như vậy. Con trỏ mà nó sẽ phân rã gần tương đương với một tham chiếu hơn là một bản sao và bạn có thể sử dụng std::array
để chuyển một tham chiếu nếu đó là những gì bạn muốn.
std::size_t
thay thế int
? xin lỗi vì nitpicking, nhưng điều này sẽ làm cho nó phổ biến.
size_t
nếu bạn muốn, mặc dù tôi không thể tưởng tượng được có nhiều trường hợp mà mảng với hơn 4 tỷ hàng hoặc cột là cần thiết.
Như Sumant đã nói, mảng đa chiều dễ sử dụng hơn rất nhiều với mảng C tích hợp sẵn std::array
.
Khi được lồng vào nhau, std::array
có thể trở nên rất khó đọc và dài dòng không cần thiết.
Ví dụ:
std::array<std::array<int, 3>, 3> arr1;
so với
char c_arr[3][3];
Ngoài ra, hãy lưu ý rằng begin()
, end()
và size()
tất cả đều trả về giá trị vô nghĩa khi bạn lồng vào nhau std::array
.
Vì những lý do này, tôi đã tạo vùng chứa mảng đa chiều có kích thước cố định của riêng mình array_2d
và array_3d
. Chúng tương tự std::array
nhưng đối với các mảng đa chiều gồm 2 và 3 chiều. Chúng an toàn hơn và không có hiệu suất kém hơn so với mảng đa chiều tích hợp sẵn. Tôi đã không bao gồm một vùng chứa cho các mảng nhiều chiều có kích thước lớn hơn 3 vì chúng không phổ biến. Trong C ++ 0x có thể tạo một phiên bản mẫu đa dạng hỗ trợ một số kích thước tùy ý.
Một ví dụ về biến thể hai chiều:
//Create an array 3 x 5 (Notice the extra pair of braces)
fsma::array_2d <double, 3, 5> my2darr = {{
{ 32.19, 47.29, 31.99, 19.11, 11.19},
{ 11.29, 22.49, 33.47, 17.29, 5.01 },
{ 41.97, 22.09, 9.76, 22.55, 6.22 }
}};
Tài liệu đầy đủ có sẵn tại đây:
http://fsma.googlecode.com/files/fsma.html
Bạn có thể tải thư viện tại đây:
arr[x][y]
, bạn không thể biết liệu arr
là một mảng mảng, một mảng con trỏ, một con trỏ tới một mảng hay một con trỏ tới một con trỏ; tất cả để triển khai đều hợp pháp, tùy thuộc vào nhu cầu của bạn. Và có lẽ hầu hết các trường hợp sử dụng trong thế giới thực cho mảng đa chiều đều yêu cầu kích thước được xác định tại thời điểm chạy.
Mảng kiểu C có sẵn trong C ++ thực sự kém linh hoạt hơn nhiều so với mảng C thực. Sự khác biệt là trong C, các kiểu mảng có thể có kích thước thời gian chạy . Sau đây là mã C hợp lệ, nhưng nó không thể được thể hiện với các mảng kiểu C ++ hoặc với các kiểu C ++ array<>
:
void foo(int bar) {
double tempArray[bar];
//Do something with the bar elements in tempArray.
}
Trong C ++, bạn sẽ phải cấp phát mảng tạm thời trên heap:
void foo(int bar) {
double* tempArray = new double[bar];
//Do something with the bar elements behind tempArray.
delete[] tempArray;
}
Điều này không thể đạt được với std::array<>
, vì bar
không được biết tại thời điểm biên dịch, nó yêu cầu sử dụng mảng kiểu C trong C ++ hoặc của std::vector<>
.
Trong khi ví dụ đầu tiên có thể được diễn đạt tương đối dễ dàng bằng C ++ (mặc dù yêu cầu new[]
và delete[]
), nhưng điều sau không thể đạt được trong C ++ mà không có std::vector<>
:
void smoothImage(int width, int height, int (*pixels)[width]) {
int (*copy)[width] = malloc(height*sizeof(*copy));
memcpy(copy, pixels, height*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y][x] = //compute smoothed value based on data around copy[y][x]
}
}
free(copy);
}
Vấn đề là, các con trỏ đến các mảng dòng int (*)[width]
không thể sử dụng độ rộng thời gian chạy trong C ++, điều này làm cho bất kỳ mã thao tác hình ảnh nào trong C ++ phức tạp hơn nhiều so với trong C. Một ví dụ về thao tác hình ảnh trong C ++ điển hình sẽ trông như thế này:
void smoothImage(int width, int height, int* pixels) {
int* copy = new int[height*width];
memcpy(copy, pixels, height*width*sizeof(*copy));
for(y = height; y--; ) {
for(x = width; x--; ) {
pixels[y*width + x] = //compute smoothed value based on data around copy[y*width + x]
}
}
delete[] copy;
}
Mã này thực hiện chính xác các tính toán giống như mã C ở trên, nhưng nó cần thực hiện tính toán chỉ mục bằng tay ở bất kỳ nơi nào các chỉ số được sử dụng . Đối với trường hợp 2D, điều này vẫn khả thi (mặc dù nó đi kèm với rất nhiều cơ hội để tính chỉ số sai). Tuy nhiên, nó thực sự khó chịu trong trường hợp 3D.
Tôi thích viết mã bằng C ++. Nhưng bất cứ khi nào tôi cần thao tác dữ liệu đa chiều, tôi thực sự tự hỏi mình có nên chuyển phần mã đó sang C.
gcc
ví dụ). C11 đã tạo ra khá nhiều thứ thú vị tùy chọn và tôi không nghĩ đó là vì họ muốn loại bỏ tính năng này. Tôi có xu hướng coi đó là một dấu hiệu cho thấy họ muốn hạ thấp trình độ để viết một trình biên dịch tuân thủ tiêu chuẩn hoàn toàn: VLA là một thứ khá khó thực hiện và nhiều mã có thể làm mà không có, vì vậy nó có ý nghĩa đối với một trình biên dịch mới trên một số nền tảng để không phải triển khai VLA ngay lập tức.
Có thể std::array
là không chậm. Nhưng tôi đã thực hiện một số điểm chuẩn bằng cách sử dụng cửa hàng đơn giản và đọc từ std :: array; Xem kết quả điểm chuẩn bên dưới (trên W8.1, VS2013 Cập nhật 4):
ARR_SIZE: 100 * 1000
Avrg = Tick / ARR_SIZE;
test_arr_without_init
==>VMem: 5.15Mb
==>PMem: 8.94Mb
==>Tick: 3132
==>Avrg: 0.03132
test_arr_with_init_array_at
==>VMem: 5.16Mb
==>PMem: 8.98Mb
==>Tick: 925
==>Avrg: 0.00925
test_arr_with_array_at
==>VMem: 5.16Mb
==>PMem: 8.97Mb
==>Tick: 769
==>Avrg: 0.00769
test_c_arr_without_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 358
==>Avrg: 0.00358
test_c_arr_with_init
==>VMem: 5.16Mb
==>PMem: 8.94Mb
==>Tick: 305
==>Avrg: 0.00305
Theo các dấu âm, mã tôi đã sử dụng nằm trong pastebin ( liên kết )
Mã lớp điểm chuẩn ở đây ;
Tôi không biết nhiều về điểm chuẩn ... Mã của tôi có thể thiếu sót
long test_arr_without_init() { return ARR_SIZE; }
void test_arr_without_init() {}
bây giờ. Bạn thực sự cần phải nhảy qua các vòng để đảm bảo mã bạn đang đo là mã bạn muốn đo.
std::array
std::array
sẽ kém hiệu suất hơn một mảng C.
at()
, nó không phải operator[]
, giống như std::vector
. Không có sự sụt giảm hiệu suất hoặc mã bị phình lên std::array
, trình biên dịch được thiết kế để tối ưu hóa loại thứ này. Và, tất nhiên, việc bổ sung chức năng đã kiểm tra là một công cụ gỡ lỗi tuyệt vời và là một lợi thế lớn. @Lou Franco: Tất cả mã C ++ có thể phụ thuộc vào thư viện Chuẩn - đó là loại thư viện dùng để làm. @Earlz: Nếu bạn không có sẵn STL, thì đó không phải là C ++, và đó là kết thúc của việc đó.
std::array
lớn hơn mức sử dụng mảng C tương đương.