ค่าเริ่มต้นเริ่มต้นของ std :: array?


106

ด้วย C ++ 11 std::arrayฉันรับประกันว่าไวยากรณ์std::array<T, N> x;จะเริ่มต้นองค์ประกอบทั้งหมดของอาร์เรย์เป็นค่าเริ่มต้นหรือไม่

แก้ไข : ถ้าไม่มีมีไวยากรณ์ที่จะทำงานกับอาร์เรย์ทั้งหมด (รวมถึงอาร์เรย์ขนาดศูนย์) เพื่อเริ่มต้นองค์ประกอบทั้งหมดเป็นค่าเริ่มต้นหรือไม่

แก้ไข : ในcppreferenceคำอธิบายตัวสร้างเริ่มต้นกล่าวว่า:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

ดังนั้นคำตอบอาจเป็นใช่ แต่ฉันต้องการให้แน่ใจว่าเป็นไปตามมาตรฐานหรือมาตรฐานในอนาคต


อย่าคิดอย่างนั้น เป็นค่าเริ่มต้นที่ประกาศไว้ดังนั้นโดยทั่วไปจึงเทียบเท่ากับT x[N]ไวยากรณ์
Rapptz

คำตอบ:


151

ตามคำจำกัดความการเริ่มต้นเริ่มต้นคือการเริ่มต้นที่เกิดขึ้นเมื่อไม่มีการระบุการเตรียมใช้งานอื่น ๆ ภาษา C ++ รับประกันคุณว่าอ็อบเจ็กต์ใด ๆที่คุณไม่ได้ระบุตัวเริ่มต้นอย่างชัดเจนจะถูกกำหนดค่าเริ่มต้น (C ++ 11 §8.5 / 11) ซึ่งรวมถึงวัตถุประเภทstd::array<T, N>และT[N] .

โปรดทราบว่ามีประเภทที่การกำหนดค่าเริ่มต้นดีฟอลต์ไม่มีผลและปล่อยให้ค่าของอ็อบเจ็กต์ไม่แน่นอน: ชนิดที่ไม่ใช่คลาสใด ๆ ที่ไม่ใช่อาร์เรย์ (§8.5 / 6) ดังนั้นอาร์เรย์ที่เริ่มต้นเริ่มต้นของวัตถุที่มีประเภทดังกล่าวจะมีค่าที่ไม่แน่นอนเช่น:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

ทั้งอาร์เรย์สไตล์ c และstd::arrayเต็มไปด้วยจำนวนเต็มของค่าที่ไม่แน่นอนเช่นเดียวกับที่plain_intมีค่าไม่แน่นอน

มีไวยากรณ์ที่ใช้กับอาร์เรย์ทั้งหมด (รวมถึงอาร์เรย์ขนาดศูนย์) เพื่อเริ่มต้นองค์ประกอบทั้งหมดเป็นค่าเริ่มต้นหรือไม่

ฉันคาดเดาว่าเมื่อคุณพูดว่า "เป็นค่าเริ่มต้น" คุณหมายถึง "เริ่มต้นองค์ประกอบทั้งหมดเป็นT{}" จริงๆ นั่นไม่ใช่การเริ่มต้นเริ่มต้นแต่เป็นค่าเริ่มต้น (8.5 / 7) คุณสามารถขอค่าเริ่มต้นได้ค่อนข้างง่ายใน C ++ 11 โดยให้การประกาศแต่ละครั้งเป็น initializer ว่าง:

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

ซึ่งจะกำหนดค่าเริ่มต้นองค์ประกอบอาร์เรย์ทั้งหมดในทางกลับกันส่งผลให้plain_old_intและสมาชิกทั้งหมดของอาร์เรย์ทั้งสองชนิดเริ่มต้นเป็นศูนย์


แล้วถ้าเป็นสมาชิกคลาส: struct X {std :: array <int, 12> dozen; X (): โหล () {} นั่นทำให้ฉันได้ศูนย์สิบสองตัวหรือเปล่า
gerardw

4
@gerardw ตามมาตรฐานใช่เลย ระวังข้อบกพร่องใน MSVC จะไม่สามารถใช้การเริ่มต้นค่าบางกรณีได้อย่างถูกต้อง
Casey

1
การเพิ่มประสิทธิภาพพูดอย่างนั้นและแก้ปัญหาด้วยboost::value_initialized ลิงก์ของพวกเขาแต่ฉันเชื่อว่า VC12 (VS2013) มีการสนับสนุนที่ดีกว่ามาก
v.oddou

1
ทำให้ฉันอยากให้ comitee เปลี่ยนมาตรฐานเป็นการเริ่มต้นค่าเริ่มต้นและค่าที่ถูกทำลายตามคำขอ ได้แก่ std :: array <int, 12> = {std :: undetermined}; หรืออะไรสักอย่าง
Viktor Sehr

ในทางปฏิบัติการเริ่มต้นบางสิ่งเป็นค่าที่ไม่แน่นอนหมายความว่าอย่างไร ทางเลือกคืออะไร?
Andrew

23

Default-initializationเป็นคำที่มาจาก Standard ซึ่งอาจหมายความว่าไม่มีการเริ่มต้นเลยดังนั้นคุณอาจหมายถึงzero-initializationเป็นศูนย์การเริ่มต้น

คำอธิบายใน cppreference.com นั้นทำให้เข้าใจผิดเล็กน้อย std::arrayเป็นคลาสรวมและถ้าประเภทองค์ประกอบเป็นแบบดั้งเดิมก็คือ POD: "ข้อมูลเก่าล้วน" โดยมีความหมายใกล้เคียงกับภาษา C ตัวสร้างที่กำหนดโดยนัยของstd::array< int, N >เป็นเรื่องเล็กน้อยที่ไม่ซึ่งไม่ได้ทำอะไรเลย

ไวยากรณ์ที่เหมือนstd::array< int, 3 >()หรือstd::array< int, 3 > x{}ที่ให้ค่าเป็นศูนย์ไม่สามารถทำได้โดยการเรียกใช้ตัวสร้าง การได้ศูนย์เป็นส่วนหนึ่งของการกำหนดค่าเริ่มต้นที่ระบุใน C ++ 11 §8.5 / 8:

ในการกำหนดค่าเริ่มต้นวัตถุประเภท T หมายถึง:

- ถ้า T เป็นประเภทคลาส (อาจมีคุณสมบัติเป็น cv) โดยไม่มีตัวสร้างเริ่มต้นที่ผู้ใช้ระบุหรือถูกลบออกไปวัตถุนั้นจะเริ่มต้นเป็นศูนย์ ... และถ้า T มีตัวสร้างเริ่มต้นที่ไม่สำคัญอ็อบเจ็กต์จะถูกกำหนดค่าเริ่มต้นโดยปริยาย

std::arrayไม่มีตัวสร้างเริ่มต้นที่ผู้ใช้ระบุดังนั้นจึงได้รับค่าเริ่มต้นเป็นศูนย์ มันมีคอนสตรัคเตอร์เริ่มต้นที่กำหนดไว้โดยปริยาย แต่เป็นเรื่องเล็กน้อยดังนั้นจึงไม่ถูกกำหนดค่าเริ่มต้นโดยปริยาย (แต่สิ่งนี้ไม่ได้สร้างความแตกต่างเนื่องจากการกำหนดค่าเริ่มต้นเล็กน้อยตามคำจำกัดความไม่มีผลในรันไทม์)

ถ้าไม่มีมีไวยากรณ์ที่จะใช้กับอาร์เรย์ทั้งหมด (รวมถึงอาร์เรย์ขนาดศูนย์) เพื่อเริ่มต้นองค์ประกอบทั้งหมดเป็นค่าเริ่มต้นหรือไม่

อาร์เรย์แบบ C และstd::arrayมีทั้งมวลรวมและวิธีการที่จะสมบูรณ์เป็นศูนย์เริ่มต้นใด ๆ = {}รวมอยู่กับไวยากรณ์ สิ่งนี้ใช้ได้ตั้งแต่ C ++ 98 โปรดสังเกตว่าอาร์เรย์สไตล์ C ต้องไม่มีขอบเขตเป็นศูนย์และนั่นsizeof (std::array< X, 0 >)ไม่ใช่ศูนย์


6

ทั้งสองT x[N];และstd::array<T, N> x;ค่าเริ่มต้นเริ่มต้นทุกองค์ประกอบของอาร์เรย์

ตัวอย่างเช่นถ้าT = std::stringทุกองค์ประกอบจะเป็นสตริงว่าง ถ้าTเป็นคลาสที่ไม่มีตัวสร้างเริ่มต้นทั้งสองจะไม่สามารถคอมไพล์ได้ ถ้าT = intทุกองค์ประกอบจะมีค่าไม่แน่นอน (เว้นแต่การประกาศนั้นจะอยู่ที่ขอบเขตเนมสเปซ)


0

ประการแรก T x [N] เริ่มต้นองค์ประกอบเริ่มต้นแม้ว่าการเริ่มต้นเริ่มต้นของประเภทสเกลาร์ T จะไม่ทำอะไรเลย ข้างต้นยังถือสำหรับ std :: array x ฉันคิดว่าสิ่งที่คุณต้องการคือการเริ่มต้นรายการ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.