Apakah anggota C ++ struct diinisialisasi ke 0 secara default?


Jawaban:


264

Mereka bukan nol jika Anda tidak menginisialisasi struct.

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

Yang kedua akan membuat semua anggota nol, yang pertama meninggalkan mereka pada nilai yang tidak ditentukan. Perhatikan bahwa ini bersifat rekursif:

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

Yang kedua akan menghasilkan p.s.{x,y}nol. Anda tidak dapat menggunakan daftar penginisialisasi agregat ini jika Anda memiliki konstruktor di struct Anda. Jika demikian, Anda harus menambahkan inisialisasi yang tepat ke konstruktor tersebut

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

Akan menginisialisasi x dan y ke 0. Perhatikan bahwa Anda dapat menggunakan x(), y()untuk menginisialisasi mereka tanpa menghiraukan tipe mereka: Itu kemudian menginisialisasi nilai, dan biasanya menghasilkan nilai awal yang tepat (0 untuk int, 0,0 untuk dua kali lipat, memanggil konstruktor default untuk ditentukan pengguna tipe yang memiliki konstruktor yang dinyatakan pengguna, ...). Ini penting terutama jika struct Anda adalah templat.


1
Ini menghasilkan banyak peringatan di kompiler saya.
River-Claire Williamson

1
Roger: Cobalah untuk menggunakan struct yang disebut dalam initializer, itulah yang saya lakukan dan saya tidak mendapatkan peringatan apa pun di VC 2012: Snapshot s = Snapshot ();
Kit10

@Johannes Schaub - litb Akan Snapshot s = {};bekerja untuk anggota non POD (untuk mem-zeroing mereka)?
ontherocks

2
C ++ 11 sekarang memungkinkan Anda untuk menginisialisasi mereka dalam definisi struct atau kelas, seperti: struct Snapshot {double x {0}; // dengan kawat gigi int y = 0; // atau hanya gaya sekolah lama 'berdasarkan penugasan' yang juga benar-benar inisialisasi};
ikku100

1
Apakah "Snapshot s = {};" bagian dari standar?
Stefan

41

Tidak, mereka bukan 0 secara default. Cara paling sederhana untuk memastikan bahwa semua nilai atau default ke 0 adalah dengan mendefinisikan konstruktor

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

Ini memastikan bahwa semua penggunaan Snapshot akan memiliki nilai yang diinisialisasi.


24
The downside adalah bahwa struct tidak lagi menjadi tipe POD, karena ia memiliki konstruktor. Itu akan memecah beberapa operasi seperti menulisnya ke file sementara.
finnw

16
@finnw: C ++ 11 memperbaiki ini, meskipun struct bukan POD, itu adalah "layout standar".
Ben Voigt

20

Secara umum, tidak. Namun, struct dinyatakan sebagai file-scope atau static dalam suatu fungsi / akan / diinisialisasi ke 0 (seperti semua variabel lain dari cakupan itu):

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
Itu benar-benar bukan asumsi yang aman. Anda tidak harus bergantung pada nilai apa pun yang tidak Anda inisialisasi
Hasturkun

24
Objek durasi penyimpanan statis selalu diinisialisasi ke nol - lihat stackoverflow.com/questions/60653/… untuk kutipan dari standar. Apakah ini gaya yang baik adalah masalah lain.
bdonlan

12

Dengan POD Anda juga dapat menulis

Snapshot s = {};

Anda tidak harus menggunakan memset di C ++, memset memiliki kelemahan bahwa jika ada non-POD dalam struct itu akan menghancurkannya.

atau seperti ini:

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

Snapshot* s = init();

@LightnessRacesinOrbit oh, wat?
Ben Sinclair

@Andy Most Vexing Parse mengubah hal-hal yang terlihat seperti ctors normal - SomeType foo();adalah yang khas, meskipun dapat terjadi dengan yang lain - menjadi definisi fungsi (dalam hal ini, fungsi fooyang mengembalikan SomeType). Maaf untuk necro, tetapi jika orang lain menemukan ini, kupikir aku akan menjawab.
Dana Gugatan Monica

8

Di C ++, gunakan konstruktor tanpa argumen. Di C Anda tidak dapat memiliki konstruktor, jadi gunakan salah satu memsetatau - solusi menarik - inisialisasi yang ditunjuk:

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

Saya percaya ini adalah C, bukan C ++. Ini akan gagal dikompilasi di bawah beberapa kompiler C ++. Saya mengalami kegagalan kompilasi di bawah Cygwin atau MinGW.
jww

3

Saya percaya jawaban yang benar adalah bahwa nilainya tidak terdefinisi. Seringkali, mereka diinisialisasi ke 0 ketika menjalankan versi debug kode. Ini biasanya tidak terjadi ketika menjalankan versi rilis.


2
Sebenarnya versi debug kebetulan sudah ada 0di tempat-tempat di memori. Ini tidak sama dengan inisialisasi!
Lightness Races dalam Orbit

3

Karena ini adalah POD (dasarnya sebuah C struct) ada sedikit bahaya dalam menginisialisasi dengan cara C:

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

atau serupa

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

Saya tidak akan pergi sejauh yang digunakan calloc()dalam program C ++.


3
Sama berlaku untuk ganda; all-bits-zero belum tentu 0,0. Namun, Anda dapat memeriksa apakah Anda memiliki IEEE754 ganda, dalam hal ini harus berfungsi.
MSalters

1

Pindahkan anggota pod ke kelas dasar untuk mempersingkat daftar penginisialisasi Anda:

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());
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.