วลีต่อไปนี้หมายความว่าอย่างไรใน C ++:
ศูนย์การเริ่มต้น
การกำหนดค่าเริ่มต้นและ
มูลค่าเริ่มต้น
นักพัฒนา C ++ ควรรู้อะไรเกี่ยวกับพวกเขาบ้าง
วลีต่อไปนี้หมายความว่าอย่างไรใน C ++:
ศูนย์การเริ่มต้น
การกำหนดค่าเริ่มต้นและ
มูลค่าเริ่มต้น
นักพัฒนา C ++ ควรรู้อะไรเกี่ยวกับพวกเขาบ้าง
คำตอบ:
สิ่งหนึ่งที่ต้องตระหนักคือ 'การกำหนดค่าเริ่มต้น' นั้นใหม่กับมาตรฐาน C ++ 2003 - มันไม่มีอยู่ในมาตรฐาน 1998 ดั้งเดิม (ฉันคิดว่ามันอาจเป็นความแตกต่างเพียงอย่างเดียวที่มากกว่าการชี้แจง) ดูคำตอบของ Kirill V. Lyadvinskyสำหรับคำจำกัดความที่ตรงจากมาตรฐาน
ดูคำตอบก่อนหน้านี้เกี่ยวกับพฤติกรรมของoperator new
เพื่อดูรายละเอียดเกี่ยวกับพฤติกรรมที่แตกต่างกันของการเริ่มต้นประเภทนี้และเมื่อพวกเขาเตะเข้า (และเมื่อพวกเขาแตกต่างจาก c ++ 98 ถึง C ++ 03):
ประเด็นหลักของคำตอบคือ:
บางครั้งหน่วยความจำที่ส่งคืนโดยผู้ดำเนินการใหม่จะเริ่มต้นได้และบางครั้งมันจะไม่ขึ้นอยู่กับว่าประเภทที่คุณเพิ่งจะเริ่มเป็น POD หรือถ้าเป็นคลาสที่มีสมาชิก POD และกำลังใช้ตัวสร้างเริ่มต้นที่คอมไพเลอร์ .
- ใน C ++ 1998 มีการกำหนดค่าเริ่มต้น 2 ประเภท: ศูนย์และค่าเริ่มต้น
- ใน C ++ 2003 การเริ่มต้นประเภทที่ 3 จะมีการเพิ่มการกำหนดค่าเริ่มต้น
จะพูดอย่างน้อยก็ค่อนข้างซับซ้อนและเมื่อวิธีการต่าง ๆ เตะเข้าเฝ้า
สิ่งหนึ่งที่ต้องระวังอย่างแน่นอนคือ MSVC ปฏิบัติตามกฎ C ++ 98 แม้ใน VS 2008 (VC 9 หรือ cl.exe เวอร์ชัน 15.x)
ตัวอย่างต่อไปนี้แสดงให้เห็นว่า MSVC และ Digital Mars ปฏิบัติตามกฎ C ++ 98 ในขณะที่ GCC 3.4.5 และ Comeau ปฏิบัติตามกฎ C ++ 03:
#include <cstdio>
#include <cstring>
#include <new>
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
int main()
{
char buf[sizeof(B)];
std::memset( buf, 0x5a, sizeof( buf));
// use placement new on the memset'ed buffer to make sure
// if we see a zero result it's due to an explicit
// value initialization
B* pB = new(buf) B(); //C++98 rules - pB->m is uninitialized
//C++03 rules - pB->m is set to 0
std::printf( "m is %d\n", pB->m);
return 0;
}
int
แต่m()
ในบรรทัดที่สามค่าเริ่มต้น m ที่สำคัญถ้าคุณเปลี่ยนไปint m;
B m;
:)
A
และC
ไม่ได้ใช้ในตัวอย่างนี้ (เป็นคำตอบที่เชื่อมโยงกัน) แม้ว่า C ++ 98 และ C ++ 03 จะใช้คำศัพท์ต่างกันเมื่ออธิบายถึงวิธีการA
และการC
สร้างผลลัพธ์ที่ได้จะเหมือนกันในทั้งสองมาตรฐาน struct B
ผลลัพธ์เฉพาะในลักษณะการทำงานที่แตกต่างกัน
struct C { C() : m() {}; ~C(); B m; };
แล้วคุณจะได้m.m
เป็น 0 แต่ถ้ามันจะเป็นค่าเริ่มต้นm
เหมือนที่คุณบอกว่า C ++ 03 m.m
จะไม่เริ่มต้นเหมือนใน C ++ 98
C ++ 03 มาตรฐาน 8.5 / 5:
หากต้องการกำหนดค่าเริ่มต้นเป็นวัตถุประเภท T หมายถึง:
- ถ้า T เป็นประเภทสเกลาร์ (3.9) วัตถุจะถูกตั้งค่าเป็น 0 (ศูนย์) แปลงเป็น T;
- ถ้า T เป็นชนิดคลาสที่ไม่รวมสมาชิกแต่ละข้อมูลที่ไม่คงที่และแต่ละ subobject ระดับฐานเป็นศูนย์เริ่มต้นได้;
- ถ้า T เป็นชนิดยูเนี่ยนสมาชิกข้อมูลที่มีชื่อแรกของวัตถุนั้นจะถูกกำหนดค่าเริ่มต้นเป็นศูนย์
- ถ้า T เป็นชนิดอาร์เรย์แต่ละองค์ประกอบจะไม่มีค่าเริ่มต้น
- ถ้า T เป็นประเภทอ้างอิงจะไม่มีการเริ่มต้นในการเริ่มต้นเริ่มต้นวัตถุประเภท T หมายถึง:
- ถ้า T เป็นประเภทคลาสที่ไม่ใช่ POD (ข้อ 9) คอนสตรัคเตอร์เริ่มต้นสำหรับ T ถูกเรียก (และการเริ่มต้นนั้นเป็นรูปแบบที่ไม่ดีถ้า T
- ถ้า T เป็นชนิดอาร์เรย์แต่ละองค์ประกอบจะถูกกำหนดค่าเริ่มต้น
- มิฉะนั้นวัตถุจะไม่มีค่าเริ่มต้นในการกำหนดค่าเริ่มต้นวัตถุประเภท T หมายถึง:
- ถ้า T เป็นประเภทคลาส (ข้อ 9) ที่มีคอนสตรัคเตอร์ที่ผู้ใช้ประกาศ (12.1) ดังนั้นคอนสตรัคค่าเริ่มต้นสำหรับ T จะถูกเรียก (และการเตรียมใช้งานนั้น ไม่มีตัวสร้างเริ่มต้นที่สามารถเข้าถึงได้);
- ถ้า T เป็นชนิดคลาสที่ไม่รวมกันโดยไม่มีคอนสตรัคเตอร์ที่ผู้ใช้ประกาศดังนั้นสมาชิกข้อมูลที่ไม่คงที่และส่วนประกอบระดับฐานของ T จะถูกกำหนดค่าเริ่มต้น
- ถ้า T เป็นประเภทอาร์เรย์ดังนั้นแต่ละองค์ประกอบจะถูกกำหนดค่าเริ่มต้น
- มิฉะนั้นวัตถุจะไม่มีค่าเริ่มต้นโปรแกรมที่เรียกใช้การเริ่มต้นเริ่มต้นหรือการกำหนดค่าเริ่มต้นของเอนทิตีของประเภทการอ้างอิงนั้นไม่ถูกต้อง หาก T เป็นชนิดที่ผ่านการรับรอง cv เวอร์ชัน T ที่ไม่ผ่านการรับรองจะถูกใช้สำหรับนิยามเหล่านี้ของการกำหนดค่าเริ่มต้นเป็นศูนย์การกำหนดค่าเริ่มต้นเริ่มต้นและการกำหนดค่าเริ่มต้น