2009-07-01 9 views

Odpowiedz

217

Nie są one zerowe, jeśli nie zainicjalizujesz struktury.

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

Drugi powoduje, że wszystkie elementy są zerowe, a pierwszy pozostawia je w nieokreślonych wartościach. Zauważ, że jest rekurencyjna:

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

Drugi uczyni p.s.{x,y} zerowy. Nie możesz użyć tych agregujących list inicjalizujących, jeśli masz konstruktory w swojej strukturze. Jeśli tak jest, trzeba będzie dodać właściwą initalization tych konstruktorów

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

zainicjuje X i Y 0. Zauważ, że możesz użyć x(), y() zainicjować je bez uwzględnienia ich typu: To wtedy inicjalizacji wartość i zwykle daje właściwą wartość początkową (0 dla int, 0.0 dla double, wywołanie domyślnego konstruktora dla typów zdefiniowanych przez użytkownika, które mają deklarowane konstruktory, ...). Jest to szczególnie ważne, jeśli struktura jest szablonem.

+1

Powoduje to wiele ostrzeżeń w moim kompilatorze. –

+1

Roger: Spróbuj użyć nazwanej struktury w inicjalizatorze, to właśnie robię i nie dostaję żadnych ostrzeżeń w VC 2012: Snapshot s = Snapshot(); – Kit10

+0

@Johannes Schaub - litb Czy 'Snapshot s = {};' działa dla członków non POD (dla zerowania ich)? – ontherocks

36

Nie, domyślnie nie mają wartości 0. Najprostszy sposób, aby zapewnić, że wszystkie wartości 0 lub domyślne jest określenie konstruktora

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

Zapewnia to, że wszystkie zastosowania Migawka inicjalizacji wartości.

+24

Wadą jest to, że struct nie jest już typem POD, ponieważ ma konstruktor. Spowoduje to przerwanie niektórych operacji, takich jak zapisanie pliku tymczasowego. – finnw

+15

@finnw: C++ 11 naprawia to, chociaż struktura nie jest POD, jest to "standardowy układ". –

3

Wierzę, że poprawna odpowiedź jest taka, że ​​ich wartości są niezdefiniowane. Często są one inicjalizowane na 0 podczas uruchamiania wersji debugowania kodu. Zwykle nie jest tak w przypadku wersji uruchomionych.

+2

W rzeczywistości wersje debugowania mają już w tych miejscach w pamięci "0". To nie jest to samo, co inicjalizacja! –

16

Ogólnie rzecz biorąc nie. Jednakże, struktura uznane jako plik-zakresu lub statycznych funkcji/będzie/jest ustawiony na 0 (podobnie jak wszystkie inne zmienne tych zakresów):

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

To naprawdę nie jest bezpieczne założenie. nie powinieneś polegać na wartości wszystkiego, czego nie zainicjowałeś. – Hasturkun

+17

Obiekty czasu trwania statycznego magazynu są zawsze inicjowane do zera - patrz http://stackoverflow.com/questions/60653/is-global-memory-initialized-in-c/ 60707 # 60707 dla cytatu ze standardu. Czy to dobry styl, to inna kwestia. – bdonlan

4

Ponieważ jest POD (zasadniczo C Struct) niewiele jest złego w inicjalizacji to tak C:

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

lub podobnie

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

nie chciałbym iść tak daleko, aby korzystać calloc() w programie C++ mimo.

+5

To nie jest przenośne. 0 wskaźnik może mieć wartość inną niż 0. –

+1

@Sergey, tak, ale ta struktura nie zawiera żadnych wskazówek. – finnw

+3

To samo dotyczy podwójnego; all-bits-zero niekoniecznie 0.0. Możesz jednak sprawdzić, czy masz dublety IEEE754, w którym to przypadku musi działać. – MSalters

7

W C++ użyj konstruktów bezargumentowych.W C nie można mieć konstruktorów, więc użyć memset lub - ciekawe rozwiązanie - część przeznaczona inicjalizatory:

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

Wierzę, że to C, a nie C++. Nie uda się go skompilować pod niektórymi kompilatorami C++. Wystąpił błąd kompilacji pod Cygwin lub MinGW. – jww

11

Z POD można również napisać

Snapshot s = {}; 

Nie należy używać memset w C++ , memset ma tę wadę, że jeśli w strukturze jest nie-POD, to go zniszczy.

lub tak:

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

Snapshot* s = init(); 
+0

[Uważaj na Mr. Most Vexing Parse] (http://codepad.org/utBvhcQ5) –

+0

@LightnessRacesinOrbit oh wat? – Andy

+0

@Andy Najbardziej Vexing Parse zmienia rzeczy, które wyglądają jak normalne ctors - 'SomeType foo();' jest typowym, choć może się zdarzyć z innymi - do definicji funkcji (w tym przypadku funkcja 'foo', która zwraca 'SomeType'). Przepraszam za necro, ale jeśli ktoś inny natknie się na to, pomyślałem, że odpowiem. –

1

członków Move strąk do klasy bazowej, aby skrócić listę 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()); 
} 
Powiązane problemy