อันนี้จริง ๆ แล้วยากมากที่จะอธิบาย แต่ฉันจะให้ไป ...
ประการแรกdimof
บอกมิติหรือจำนวนองค์ประกอบในอาร์เรย์ (ฉันเชื่อว่า "มิติ" เป็นคำศัพท์ที่ต้องการในสภาพแวดล้อมการเขียนโปรแกรม Windows)
สิ่งนี้มีความจำเป็นเพราะC++
และC
ไม่ได้ให้วิธีแบบเนทีฟในการกำหนดขนาดของอาร์เรย์
บ่อยครั้งที่ผู้คนคิดว่าsizeof(myArray)
จะใช้งานได้ แต่จริง ๆ แล้วจะทำให้คุณมีขนาดในหน่วยความจำมากกว่าจำนวนองค์ประกอบ แต่ละองค์ประกอบอาจใช้หน่วยความจำมากกว่า 1 ไบต์!
sizeof(myArray) / sizeof(myArray[0])
ต่อไปพวกเขาอาจจะพยายาม นี่จะทำให้ขนาดในหน่วยความจำของอาร์เรย์หารด้วยขนาดขององค์ประกอบแรก มันใช้ได้และใช้กันอย่างแพร่หลายในC
รหัส ปัญหาสำคัญของเรื่องนี้คือมันจะปรากฏขึ้นหากคุณผ่านตัวชี้แทนที่จะเป็นอาร์เรย์ ขนาดของตัวชี้ในหน่วยความจำมักจะเป็น 4 หรือ 8 ไบต์แม้ว่าสิ่งที่ชี้ไปอาจเป็นอาร์เรย์ขององค์ประกอบ 1000s
ดังนั้นสิ่งต่อไปที่ต้องลองC++
คือใช้เทมเพลตเพื่อบังคับบางอย่างที่ใช้งานได้กับอาร์เรย์เท่านั้นและจะให้ข้อผิดพลาดคอมไพเลอร์บนตัวชี้ ดูเหมือนว่านี้:
template <typename T, std::size_t N>
std::size_t ArraySize(T (&inputArray)[N])
{
return N;
}
//...
float x[7];
cout << ArraySize(x); // prints "7"
เทมเพลตจะทำงานกับอาเรย์เท่านั้น มันจะอนุมานประเภท (ไม่จำเป็นจริงๆ แต่ต้องอยู่ที่นั่นเพื่อให้ได้เทมเพลตทำงาน) และขนาดของอาร์เรย์จากนั้นจะส่งคืนขนาด วิธีเขียนเทมเพลตไม่สามารถทำงานกับพอยน์เตอร์ได้
โดยปกติแล้วคุณสามารถหยุดที่นี่และนี่คือใน C ++ std::size
มาตรฐานไลบรารีเป็น
คำเตือน: ด้านล่างนี่มันเข้าสู่ดินแดนนักกฎหมายด้านภาษา
นี่เจ๋งทีเดียว แต่ก็ยังล้มเหลวในกรณีที่ขอบชัดเจน:
struct Placeholder {
static float x[8];
};
template <typename T, int N>
int ArraySize (T (&)[N])
{
return N;
}
int main()
{
return ArraySize(Placeholder::x);
}
โปรดทราบว่าอาร์เรย์x
จะประกาศแต่ไม่ได้กำหนดไว้ การเรียกฟังก์ชั่น (เช่นArraySize
) กับมันx
จะต้องมีการกำหนดไว้
In function `main':
SO.cpp:(.text+0x5): undefined reference to `Placeholder::x'
collect2: error: ld returned 1 exit status
คุณไม่สามารถลิงก์นี้
รหัสที่คุณมีในคำถามเป็นวิธีแก้ไข แทนที่จะจริงเรียกฟังก์ชั่นที่เราประกาศฟังก์ชั่นที่ส่งกลับวัตถุของว่าขนาดที่เหมาะสมด้วย จากนั้นเราก็ใช้sizeof
กลอุบายนั้น
มันมีลักษณะเหมือนที่เราเรียกใช้ฟังก์ชัน แต่sizeof
เป็นอย่างหมดจดสร้างรวบรวมเวลาดังนั้นฟังก์ชั่นไม่เคยได้รับการเรียก
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
หมายเหตุคุณไม่สามารถส่งคืนอาร์เรย์จากฟังก์ชันได้ แต่คุณสามารถส่งคืนการอ้างอิงไปยังอาร์เรย์ได้
จากนั้นDimofSizeHelper(myArray)
เป็นนิพจน์ที่มีชนิดเป็นอาร์เรย์บนN
char
s การแสดงออกไม่จำเป็นต้องสามารถใช้งานได้จริง แต่มันก็สมเหตุสมผลที่เวลารวบรวม
ดังนั้นsizeof(DimofSizeHelper(myArray))
จะบอกขนาดในเวลารวบรวมของสิ่งที่คุณจะได้รับถ้าคุณเรียกใช้ฟังก์ชันจริง แม้ว่าเราจะไม่เรียกมันว่าจริง
ไม่ต้องกังวลหากบล็อกสุดท้ายนั้นไม่สมเหตุสมผล มันเป็นกลอุบายที่แปลกประหลาดในการแก้ไขกรณีที่แปลกประหลาด นี่คือเหตุผลที่คุณไม่ได้เขียนโค้ดประเภทนี้ด้วยตัวคุณเองและให้ผู้ใช้ไลบรารี่กังวลเกี่ยวกับเรื่องไร้สาระประเภทนี้
std::array
หรือstd::vector
....