เนื่องจากstd::list
และstd::vector
มีอยู่มีเหตุผลที่จะใช้อาร์เรย์ C แบบดั้งเดิมใน C ++ หรือไม่หรือควรหลีกเลี่ยงเช่นเดียวกับmalloc
?
เนื่องจากstd::list
และstd::vector
มีอยู่มีเหตุผลที่จะใช้อาร์เรย์ C แบบดั้งเดิมใน C ++ หรือไม่หรือควรหลีกเลี่ยงเช่นเดียวกับmalloc
?
คำตอบ:
ใน C ++ 11 ที่std::array
พร้อมใช้งานคำตอบคือ "ใช่อาร์เรย์ควรหลีกเลี่ยง" ก่อนหน้า C ++ 11 คุณอาจต้องใช้อาร์เรย์ C เพื่อจัดสรรอาร์เรย์ในที่จัดเก็บอัตโนมัติ (เช่นบนสแตก)
แน่นอนแม้ว่าจะมีstd::array
ใน C ++ 11 แต่ในทางปฏิบัติสำหรับข้อมูลคงที่เท่านั้น อาร์เรย์สไตล์ C มีข้อดีที่สำคัญสามประการ
std::vector
ดังนี้
ไม่ต้องการการจัดสรรแบบไดนามิก ด้วยเหตุนี้อาร์เรย์สไตล์ C จึงเป็นที่ต้องการซึ่งคุณน่าจะมีอาร์เรย์ขนาดเล็กจำนวนมาก พูดอะไรบางอย่างเช่นจุด n มิติ:
template <typename T, int dims>
class Point
{
T myData[dims];
// ...
};
โดยทั่วไปแล้วเราอาจนึกภาพว่าdims
จะมีขนาดเล็กมาก (2 หรือ 3)
T
เป็นชนิดในตัว ( double
) และคุณอาจได้รับ
std::vector<Point>
องค์ประกอบหลายล้านรายการ แน่นอนว่าคุณไม่ต้องการการจัดสรรแบบไดนามิกจำนวน 3 คู่
การสนับสนุนการเริ่มต้นแบบคงที่ นี่เป็นเพียงปัญหาสำหรับข้อมูลคงที่ซึ่งบางสิ่งเช่น:
struct Data { int i; char const* s; };
Data const ourData[] =
{
{ 1, "one" },
{ 2, "two" },
// ...
};
นี้มักจะเป็นที่นิยมในการใช้เวกเตอร์ (และstd::string
) เพราะมันหลีกเลี่ยงทุกคำสั่งของการเริ่มต้นปัญหา; ข้อมูลถูกโหลดไว้ล่วงหน้าก่อนที่จะเรียกใช้โค้ดจริงใด ๆ
สุดท้ายที่เกี่ยวข้องกับข้างต้นคอมไพเลอร์สามารถคำนวณขนาดจริงของอาร์เรย์ได้จาก initializers คุณไม่จำเป็นต้องนับพวกเขา
หากคุณสามารถเข้าถึง C ++ 11 ได้ให้std::array
แก้ปัญหาสองข้อแรกและควรใช้ตามความต้องการของอาร์เรย์สไตล์ C ในกรณีแรก อย่างไรก็ตามมันไม่ได้อยู่ที่สามและการมีขนาดคอมไพเลอร์ในอาร์เรย์ตามจำนวนตัวเริ่มต้นยังคงเป็นเหตุผลที่ถูกต้องที่จะชอบอาร์เรย์สไตล์ C
int i[] = { 1, 2, 3 };
ความต้องการที่จะเปลี่ยนแปลงตนเองเพื่อ int i[] = { 1, 2, 3, 4 };
array<int, 3>
array<int, 4>
make_array
ฟังก์ชันคล้ายกับmake_pair
ฯลฯ Hat-tip ถึง@R มาตินเฟอร์นันเด
std::array
ใน C ++ 11 ก็ตาม [ควรใช้] ในทางปฏิบัติสำหรับข้อมูลคงที่เท่านั้น"
อย่าพูดว่า "ไม่เคย" แต่ฉันยอมรับว่าบทบาทของพวกเขาลดลงอย่างมากจากโครงสร้างข้อมูลที่แท้จริงจาก STL
ฉันจะบอกด้วยว่าการห่อหุ้มภายในวัตถุควรลดผลกระทบของตัวเลือกเช่นนี้ให้น้อยที่สุด หากอาร์เรย์เป็นสมาชิกข้อมูลส่วนตัวคุณสามารถสลับเข้าหรือออกได้โดยไม่ส่งผลกระทบต่อไคลเอ็นต์ของคลาสของคุณ
ฉันทำงานเกี่ยวกับระบบสำคัญด้านความปลอดภัยที่คุณไม่สามารถใช้การจัดสรรหน่วยความจำแบบไดนามิกได้ หน่วยความจำจะต้องอยู่ในสแต็กเสมอ ดังนั้นในกรณีนี้คุณจะใช้อาร์เรย์เนื่องจากขนาดคงที่ในเวลาคอมไพล์
std::array<T>
จัดสรรบนสแต็กและโดยทั่วไปไม่มีค่าใช้จ่ายในอาร์เรย์ดิบ
array
ในc++
ช่วยให้คุณมีทางเลือกที่รวดเร็วขนาดคงที่สำหรับขนาดไดนามิกstd::vector
และstd::list
. std :: arrayเป็นหนึ่งในส่วนเสริมในc++11
. มันให้ประโยชน์ของคอนเทนเนอร์ std ในขณะที่ยังคงให้ความหมายประเภทรวมของอาร์เรย์สไตล์ C
ดังนั้นc++11
ฉันจะใช้std::array
ในที่ที่จำเป็นอย่างแน่นอนทับเวกเตอร์ แต่ฉันจะหลีกเลี่ยงอาร์เรย์สไตล์ C ในC++03
.
ส่วนใหญ่มักจะไม่vectors
ฉันไม่สามารถคิดว่าเหตุผลที่จะใช้อาร์เรย์ดิบมากกว่าการพูด ถ้ารหัสใหม่ .
คุณอาจต้องหันไปใช้อาร์เรย์หากไลบรารีของคุณต้องเข้ากันได้กับรหัสที่คาดว่าอาร์เรย์และตัวชี้ดิบ
vector.data()
ใน C ++ 11 หรือ&vector.front()
ก่อนหน้านี้
ฉันรู้ว่าผู้คนจำนวนมากกำลังชี้ให้เห็น std :: array สำหรับการจัดสรรอาร์เรย์บนสแต็กและ std :: vector สำหรับ heap แต่ดูเหมือนจะไม่สนับสนุนการจัดตำแหน่งที่ไม่ใช่เนทีฟ หากคุณกำลังทำรหัสตัวเลขชนิดใด ๆ ที่คุณต้องการใช้คำแนะนำ SSE หรือ VPX (จึงต้องมีการจัดตำแหน่ง 128 หรือ 256 ไบต์ตามลำดับ) อาร์เรย์ C จะยังคงเป็นทางออกที่ดีที่สุดของคุณ
ฉันจะบอกว่าอาร์เรย์ยังคงมีประโยชน์ถ้าคุณจัดเก็บข้อมูลคงที่เพียงเล็กน้อยทำไมไม่
ข้อดีเพียงอย่างเดียวของอาร์เรย์ (แน่นอนว่ารวมอยู่ในบางสิ่งที่จะจัดการการจัดสรรตำแหน่งโดยอัตโนมัติเมื่อจำเป็น) ที่std::vector
ฉันคิดได้คือvector
ไม่สามารถส่งต่อความเป็นเจ้าของข้อมูลได้เว้นแต่คอมไพเลอร์ของคุณจะรองรับ C ++ 11 และย้ายตัวสร้าง
swap
โดยใช้
อาร์เรย์สไตล์ C เป็นโครงสร้างข้อมูลพื้นฐานดังนั้นจะมีบางกรณีที่ควรใช้ อย่างไรก็ตามสำหรับกรณีทั่วไปให้ใช้โครงสร้างข้อมูลขั้นสูงที่ปัดเศษออกจากมุมของข้อมูลพื้นฐาน C ++ ช่วยให้คุณทำสิ่งที่น่าสนใจและมีประโยชน์ด้วยหน่วยความจำซึ่งหลายอย่างทำงานร่วมกับอาร์เรย์ธรรมดา
std::array
s อย่างไร ทั้งสองในหลาย ๆ กรณีจะถูกคอมไพล์เป็นแอสเซมบลีเดียวกัน
std::array
ได้กำหนดความหมายไว้อย่างแม่นยำซึ่งสร้างขึ้นที่ด้านบนของอาร์เรย์แบบคงที่
คุณควรใช้คอนเทนเนอร์ STL ภายใน แต่คุณไม่ควรส่งพอยน์เตอร์ไปยังคอนเทนเนอร์ดังกล่าวระหว่างโมดูลต่างๆมิฉะนั้นคุณจะต้องตกอยู่ในนรกแห่งการพึ่งพา ตัวอย่าง:
std::string foo;
// fill foo with stuff
myExternalOutputProc(foo.c_str());
เป็นทางออกที่ดีมาก แต่ไม่ใช่
std::string foo;
// fill foo with stuff
myExternalOutputProc(&foo);
เหตุผลก็คือ std :: string สามารถใช้งานได้หลายวิธี แต่สตริง c จะเป็นสตริงสไตล์ c เสมอ