สมาชิกของโครงสร้าง C ++ เริ่มต้นเป็น 0 โดยค่าเริ่มต้นหรือไม่


200

ฉันมีสิ่งนี้struct:

struct Snapshot
{
    double x; 
    int y;
};

ฉันต้องการxและyเป็น 0 พวกเขาจะเป็น 0 โดยค่าเริ่มต้นหรือฉันต้องทำ:

Snapshot s = {0,0};

มีวิธีอื่นใดอีกในการทำให้โครงสร้างเป็นศูนย์?


ใช้ std :: map <> และส่งกลับ 0 เมื่อไม่มีคีย์
จอนนี่

คำตอบ:


263

มันจะไม่เป็นโมฆะถ้าคุณไม่ได้เตรียมโครงสร้าง

Snapshot s; // receives no initialization
Snapshot s = {}; // value initializes all members

ที่สองจะทำให้สมาชิกทุกคนเป็นศูนย์แรกที่พวกเขาออกจากค่าที่ไม่ได้ระบุ โปรดทราบว่ามันซ้ำ:

struct Parent { Snapshot s; };
Parent p; // receives no initialization
Parent p = {}; // value initializes all members

ที่สองจะทำให้p.s.{x,y}เป็นศูนย์ คุณไม่สามารถใช้รายการเริ่มต้นรวมเหล่านี้หากคุณมี Constructor ใน struct หากเป็นเช่นนั้นคุณจะต้องเพิ่มการทำให้เป็นจริงที่เหมาะสมกับตัวสร้างเหล่านั้น

struct Snapshot {
    int x;
    double y;
    Snapshot():x(0),y(0) { }
    // other ctors / functions...
};

จะเริ่มต้นทั้ง x และ y เป็น 0 โปรดทราบว่าคุณสามารถใช้x(), y()เพื่อเริ่มต้นพวกเขาโดยไม่คำนึงถึงประเภทของพวกเขานั่นคือค่าเริ่มต้นแล้วและมักจะให้ค่าเริ่มต้นที่เหมาะสม (0 สำหรับ int, 0.0 สำหรับสองครั้ง ประเภทที่ผู้ใช้ประกาศ constructors, ... สิ่งนี้มีความสำคัญโดยเฉพาะอย่างยิ่งถ้า struct ของคุณเป็นแม่แบบ


1
สิ่งนี้ทำให้เกิดคำเตือนมากมายในคอมไพเลอร์ของฉัน
River-Claire Williamson

1
Roger: ลองใช้ struct ที่มีชื่อใน initializer นั่นคือสิ่งที่ฉันทำและฉันไม่ได้รับคำเตือนใด ๆ ใน VC 2012: Snapshot s = Snapshot ();
Kit10

@Johannes Schaub - litb จะSnapshot s = {};ทำงานกับสมาชิกที่ไม่ได้เป็น POD (สำหรับการ zeroing พวกเขา) หรือไม่?
ontherocks

2
C ++ 11 ตอนนี้อนุญาตให้คุณเริ่มต้นพวกเขาในความหมายของ struct หรือคลาสเช่น: struct Snapshot {double x {0} // ด้วยเครื่องหมายวงเล็บ int y = 0; // หรือเพียงแค่รูปแบบโรงเรียนเก่า 'โดยมอบหมาย' ซึ่งเป็นการเริ่มต้นจริง ๆ ด้วย};
ikku100

1
คือ "Snapshot s = {};" เป็นส่วนหนึ่งของมาตรฐานหรือไม่
Stefan

40

ไม่พวกเขาไม่ใช่ 0 โดยค่าเริ่มต้น วิธีที่ง่ายที่สุดเพื่อให้แน่ใจว่าค่าทั้งหมดหรือค่าเริ่มต้นเป็น 0 คือการกำหนดคอนสตรัคเตอร์

Snapshot() : x(0), y(0) {
}

วิธีนี้ช่วยให้มั่นใจได้ว่าการใช้ภาพรวมทั้งหมดจะมีค่าเริ่มต้น


24
ข้อเสียคือโครงสร้างไม่ได้เป็นประเภท POD อีกต่อไปเพราะมีคอนสตรัคเตอร์ ที่จะทำลายการดำเนินการบางอย่างเช่นการเขียนไปยังไฟล์ชั่วคราว
finnw

16
@finnw: C ++ 11 แก้ไขสิ่งนี้แม้ว่า struct ไม่ใช่ POD แต่เป็น "โครงร่างมาตรฐาน"
Ben Voigt

19

โดยทั่วไปไม่มี อย่างไรก็ตามโครงสร้างประกาศเป็นขอบเขตไฟล์หรือคงที่ในฟังก์ชั่น / จะ / จะเริ่มต้นเป็น 0 (เช่นเดียวกับตัวแปรอื่น ๆ ทั้งหมดของขอบเขตเหล่านั้น):

int x; // 0
int y = 42; // 42
struct { int a, b; } foo; // 0, 0

void foo() {
  struct { int a, b; } bar; // undefined
  static struct { int c, d; } quux; // 0, 0
}

1
นั่นไม่ใช่ข้อสันนิษฐานที่ปลอดภัย คุณไม่ควรวางใจในคุณค่าของสิ่งใดก็ตามที่คุณไม่ได้เริ่มต้น
Hasturkun

24
วัตถุระยะเวลาการจัดเก็บแบบคงที่จะเริ่มต้นเป็นศูนย์เสมอ - ดูstackoverflow.com/questions/60653/…สำหรับการอ้างอิงจากมาตรฐาน ไม่ว่าจะเป็นสไตล์ที่ดีก็เป็นอีกเรื่องหนึ่ง
bdonlan

12

ด้วย POD คุณสามารถเขียน

Snapshot s = {};

คุณไม่ควรใช้ memset ใน C ++ memset มีข้อเสียเปรียบว่าถ้าไม่มี POD ในโครงสร้างมันจะทำลายมัน

หรือเช่นนี้

struct init
{
  template <typename T>
  operator T * ()
  {
    return new T();
  }
};

Snapshot* s = init();

@LightnessRacesinOrbit โอ้วัดอะไร
เบ็นซินแคลร์

@Andy Most Vexing Parse เปลี่ยนสิ่งต่าง ๆ ที่ดูเหมือน ctors ปกติ - SomeType foo();เป็นสิ่งปกติแม้ว่ามันจะเกิดขึ้นกับคนอื่น - ในนิยามฟังก์ชัน (ในกรณีนั้นคือฟังก์ชันfooที่ส่งคืนSomeType) ขออภัยสำหรับ necro แต่ถ้าใครอื่นสะดุดนี้ฉันคิดว่าฉันตอบ
คดีฟ้องร้องกองทุนโมนิก้า

7

ใน C ++ ให้ใช้ตัวสร้างแบบไม่มีอาร์กิวเมนต์ ใน C คุณไม่มีคอนสตรัคเตอร์ให้ใช้memsetวิธีแก้ปัญหาที่น่าสนใจ - initializers ที่กำหนด:

struct Snapshot s = { .x = 0.0, .y = 0.0 };

ฉันเชื่อว่านี่คือ C ไม่ใช่ C ++ มันจะล้มเหลวในการรวบรวมภายใต้คอมไพเลอร์ C ++ บางตัว ฉันประสบปัญหาการคอมไพล์ล้มเหลวภายใต้ Cygwin หรือ MinGW
jww

3

ฉันเชื่อว่าคำตอบที่ถูกต้องคือค่าของพวกเขาไม่ได้กำหนด บ่อยครั้งที่มันถูกเตรียมใช้งานเป็น 0 เมื่อเรียกใช้รหัสการตรวจแก้จุดบกพร่องของรหัสรุ่น กรณีนี้มักจะไม่เกิดขึ้นเมื่อเรียกใช้รุ่นที่วางจำหน่าย


2
ที่จริงแล้วเวอร์ชันของการดีบักนั้นมีอยู่แล้ว0ในหน่วยความจำเหล่านั้น นี่ไม่ใช่การเริ่มต้นครั้งแรก!
การแข่งขัน Lightness ใน Orbit

3

เนื่องจากนี่คือ POD (โดยพื้นฐานแล้วคือโครงสร้าง C) จึงมีอันตรายเล็กน้อยในการเริ่มต้นวิธี C:

Snapshot s;
memset(&s, 0, sizeof (s));

หรือในทำนองเดียวกัน

Snapshot *sp = new Snapshot;
memset(sp, 0, sizeof (*sp));

ฉันจะไม่ไปไกลเท่าที่จะใช้calloc()ในโปรแกรม C ++


3
ถือเดียวกันสำหรับสองครั้ง; all-bits-zero ไม่จำเป็นต้องเป็น 0.0 อย่างไรก็ตามคุณสามารถตรวจสอบว่าคุณมี IEEE754 เป็นสองเท่าหรือไม่ซึ่งในกรณีนี้จะต้องใช้งานได้
MSalters

1

ย้ายสมาชิกพ็อดไปที่คลาสพื้นฐานเพื่อย่อรายการ initializer ของคุณ:

struct foo_pod
{
    int x;
    int y;
    int z;
};

struct foo : foo_pod
{
    std::string name;
    foo(std::string name)
        : foo_pod()
        , name(name)
    {
    }
};

int main()
{
    foo f("bar");
    printf("%d %d %d %s\n", f.x, f.y, f.z, f.name.c_str());
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.