Đây thực sự là một vấn đề rất khó giải thích, nhưng tôi sẽ thử ...
Đầu tiên, dimof
cho bạn biết kích thước hoặc số phần tử trong một mảng. (Tôi tin rằng "thứ nguyên" là thuật ngữ ưa thích trong môi trường lập trình Windows).
Điều này là cần thiết bởi vì C++
và C
không cung cấp cho bạn một cách riêng để xác định kích thước của một mảng.
Thông thường mọi người cho rằng sizeof(myArray)
sẽ hoạt động, nhưng điều đó thực sự sẽ cung cấp cho bạn kích thước trong bộ nhớ, thay vì số lượng phần tử. Mỗi phần tử có thể mất hơn 1 byte bộ nhớ!
Tiếp theo, họ có thể thử sizeof(myArray) / sizeof(myArray[0])
. Điều này sẽ cho kích thước trong bộ nhớ của mảng, chia cho kích thước của phần tử đầu tiên. Nó ổn, và được sử dụng rộng rãi trong C
mã. Vấn đề chính với điều này là nó sẽ xuất hiện để hoạt động nếu bạn vượt qua một con trỏ thay vì một mảng. Kích thước của một con trỏ trong bộ nhớ thường sẽ là 4 hoặc 8 byte, mặc dù thứ mà nó trỏ đến có thể là một mảng gồm 1000 phần tử.
Vì vậy, điều tiếp theo cần thử C++
là sử dụng các mẫu để buộc một cái gì đó chỉ hoạt động cho các mảng và sẽ gây ra lỗi trình biên dịch trên một con trỏ. Nó trông như thế này:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
Mẫu sẽ chỉ làm việc với một mảng. Nó sẽ suy ra kiểu (không thực sự cần thiết, nhưng phải ở đó để làm cho mẫu hoạt động) và kích thước của mảng, sau đó nó trả về kích thước. Cách viết mẫu không thể làm việc với một con trỏ.
Thông thường bạn có thể dừng ở đây, và đây là trong Libary Standard C ++ như std::size
.
Cảnh báo: bên dưới đây, nó được đưa vào lãnh thổ luật sư ngôn ngữ đầy lông.
Điều này là khá mát mẻ, nhưng vẫn thất bại trong một trường hợp cạnh tối nghĩa:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
Lưu ý rằng mảng x
được khai báo , nhưng không được xác định . Để gọi một hàm (nghĩa là ArraySize
) với nó, x
phải được xác định .
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
Bạn không thể liên kết này.
Mã bạn có trong câu hỏi là một cách xung quanh đó. Thay vì thực sự gọi một hàm, chúng ta khai báo một hàm trả về một đối tượng có kích thước chính xác . Sau đó, chúng tôi sử dụng các sizeof
mẹo trên đó.
Có vẻ như chúng ta gọi hàm, nhưng sizeof
hoàn toàn là cấu trúc thời gian biên dịch, vì vậy hàm thực sự không bao giờ được gọi.
template <typename T, size_t N>
char(&DimofSizeHelper(T(&array)[N]))[N];
^^^^ ^ ^^^
// a function that returns a reference to array of N chars - the size of this array in memory will be exactly N bytes
Lưu ý rằng bạn thực sự không thể trả về một mảng từ một hàm, nhưng bạn có thể trả về một tham chiếu đến một mảng.
Sau đó DimofSizeHelper(myArray)
là một biểu thức có kiểu là một mảng trên N
char
s. Biểu thức không thực sự phải chạy được, nhưng nó có ý nghĩa tại thời gian biên dịch.
Do đó sizeof(DimofSizeHelper(myArray))
sẽ cho bạn biết kích thước tại thời gian biên dịch của những gì bạn sẽ nhận được nếu bạn thực sự gọi hàm. Mặc dù chúng tôi không thực sự gọi nó.
Đừng lo lắng nếu khối cuối cùng không có ý nghĩa gì. Đó là một mẹo kỳ quái để làm việc xung quanh một trường hợp cạnh kỳ quái. Đây là lý do tại sao bạn không tự viết loại mã này và để những người triển khai thư viện lo lắng về loại vô nghĩa này.
std::array
haystd::vector
....