(ที่มา: ฉันมีประสบการณ์ในการใช้คอมไพเลอร์ C และ C ++)
อาร์เรย์ที่มีความยาวแปรผันใน C99 นั้นเป็นความผิดพลาดโดยทั่วไป เพื่อที่จะสนับสนุน VLAs C99 ต้องทำสิ่งต่อไปนี้ให้เป็นเรื่องปกติ:
sizeof x
ไม่คงที่ตลอดเวลาการรวบรวม; คอมไพเลอร์บางครั้งต้องสร้างรหัสเพื่อประเมินsizeof
-expression ที่รันไทม์
ช่วยให้ Vlas สองมิติ ( int A[x][y]
) ที่จำเป็นไวยากรณ์ใหม่สำหรับการประกาศฟังก์ชั่นที่ใช้ 2D Vlas void foo(int n, int A[][*])
เป็นพารามิเตอร์:
มีความสำคัญน้อยกว่าในโลก C ++ แต่มีความสำคัญอย่างยิ่งสำหรับกลุ่มเป้าหมายของโปรแกรมเมอร์ระบบฝังตัวการประกาศ VLA หมายถึงการ chomping สแต็กขนาดใหญ่โดยพลการของคุณ นี่เป็นstack-overflow ที่รับประกันและมีข้อผิดพลาด (ทุกครั้งที่คุณประกาศint A[n]
คุณจะยืนยันโดยปริยายว่าคุณมีสแต็กขนาด 2GB เพื่อสำรองไว้หากคุณรู้ว่า " n
น้อยกว่า 1,000 ที่นี่" แน่นอนคุณต้องประกาศint A[1000]
แทนค่า 32 บิตn
สำหรับ1000
การรับเข้า คุณไม่รู้ว่าพฤติกรรมของโปรแกรมของคุณควรเป็นอย่างไร)
โอเคเรามาพูดถึง C ++ กันดีกว่า ใน C ++ เรามีความแตกต่างที่ชัดเจนระหว่าง "ระบบพิมพ์" และ "ระบบคุ้มค่า" ที่ C89 ทำ ... แต่เราได้เริ่มต้นใช้มันในวิธีที่ C ไม่มี ตัวอย่างเช่น:
template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s; // equivalently, S<int[n]> s;
หากn
ไม่มีค่าคงที่เวลาคอมไพล์ (เช่นถ้าA
เป็นชนิดดัดแปลงที่แปรปรวน) แล้วอะไรบนโลกจะเป็นประเภทของS
? หากว่าS
ชนิด 's ยังได้รับการพิจารณาเท่านั้นที่รันไทม์?
เกี่ยวกับสิ่งนี้:
template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);
myfunc
คอมไพเลอร์จะต้องสร้างรหัสสำหรับการเริ่มของบางส่วน รหัสนั้นควรมีลักษณะอย่างไร เราจะสร้างโค้ดนั้นได้อย่างไรถ้าเราไม่รู้ชนิดของA1
เวลาคอมไพล์
ที่เลวร้ายยิ่งถ้ามันเกิดขึ้นตอนรันไทม์นั้นn1 != n2
งั้น!std::is_same<decltype(A1), decltype(A2)>()
เหรอ? ในกรณีนั้นการเรียกไปยังmyfunc
ไม่ควรรวบรวมเพราะการลดประเภทเทมเพลตควรล้มเหลว! เราจะเลียนแบบพฤติกรรมนั้นในรันไทม์ได้อย่างไร?
โดยพื้นฐานแล้ว C ++ กำลังเคลื่อนไปในทิศทางของการตัดสินใจมากขึ้นเรื่อย ๆ ในการรวบรวมเวลา : การสร้างโค้ดเทมเพลตconstexpr
การประเมินฟังก์ชันและอื่น ๆ ในขณะเดียวกันก็กำลังยุ่ง C99 ผลักดันประเพณีรวบรวมเวลาการตัดสินใจ (เช่นsizeof
) ลงในรันไทม์ กับในใจมันไม่ได้จริงๆแม้จะให้ความรู้สึกที่จะใช้จ่ายความพยายามใด ๆพยายามที่จะบูรณาการ Vlas C99 สไตล์เป็น C ++?
ตามที่ผู้ตอบคำถามทุกคนได้ชี้ให้เห็นแล้ว C ++ มีกลไกการจัดสรรฮีปมากมาย ( std::unique_ptr<int[]> A = new int[n];
หรือstd::vector<int> A(n);
เป็นสิ่งที่ชัดเจน) เมื่อคุณต้องการถ่ายทอดความคิด "ฉันไม่รู้ว่าต้องใช้แรมมากแค่ไหน" และ C ++ ให้รูปแบบการจัดการข้อยกเว้นที่ดีสำหรับการจัดการกับสถานการณ์ที่หลีกเลี่ยงไม่ได้ว่าจำนวนของ RAM ที่คุณต้องการมากกว่าจำนวน RAM ที่คุณมี แต่หวังว่าคำตอบนี้จะช่วยให้คุณมีความคิดที่ดีว่าทำไม VLAs สไตล์ C99 จึงไม่เหมาะสำหรับ C ++ - และไม่เหมาะกับ C99 ;)
ดูข้อมูลเพิ่มเติมเกี่ยวกับหัวข้อได้ที่N3810 "ทางเลือกสำหรับส่วนขยาย Array" , กระดาษตุลาคมของ Vjs ของ Bjarne Stroustrup ในเดือนตุลาคม 2013 POV ของ Bjarne นั้นแตกต่างจากของฉันมาก N3810 มุ่งเน้นไปที่การหาไวยากรณ์ C ++ ish ที่ดีสำหรับสิ่งต่าง ๆ และในการลดการใช้อาร์เรย์ดิบใน C ++ ในขณะที่ฉันมุ่งเน้นไปที่ความหมายของ metaprogramming และระบบพิมพ์ ฉันไม่รู้ว่าเขาเห็นว่า metaprogramming / typesystem implants แก้ไขแก้ไขได้หรือไม่สนใจเลย
โพสต์บล็อกที่ดีที่ได้รับความนิยมมากในจุดเดียวกันนี้คือ"การใช้อาร์เรย์ความยาวแปรผันที่ถูกกฎหมาย" (Chris Wellons, 2019-10-27)