PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : c/c++ Strukturen mit "0" initialisieren


Gast
2011-03-15, 13:33:42
Hallo,

Ist es zulässig, bzw. sicher Strukturen mit = {0} zu initialisieren?

Mal ein Beispiel:


typedef struct _MeineDaten
{
int datenA
int datenB
int datenC
} MeineDaten


main()
{

// Variante 1
MeineDaten mMydata;
memset(&mMydata, 0, sizeof(MeineDaten));

// Variante 2
MeineDaten mMydata = {0};

}



Variante 2 ist ja etwas kürzer nur frag ich mich ob das nun so ok ist oder ob es da potenziell irgendwelche Probleme geben könnte? Macht es irgendeinen Unterschied ob ich nun Variante 1 oder 2 verwende?

Danke

Gast
2011-03-15, 13:49:40
Überleg mal genau was du da machst...
Bau einen Konstruktor dran. Alles andere ist ein Spiel mit dem Feuer.

Memset ist außerdem nicht ohne Grund eine Stringfunktion. Willst du das was anderes als Nullen in 32 Bit Integers reinschreiben, steht garantiert nicht der gewünschte Wert in deinen Variablen.

Exxtreme
2011-03-15, 15:01:43
Joa, ein Kunstruktor oder ein spezielle Funktion, die die Variablen setzt wäre wohl angebrachter als Speicherbereiche zu überschreiben.

Coda
2011-03-15, 16:24:22
= {0} initialisiert nur das erste Element des ersten Members mit 0. Also nein.
Edit: Stimmt nicht. Wenn man ein Element initialisiert wird der Rest so initialisiert als wäre es statisch initialisiert worden, also im Falle von ints und Pointern mit 0. Wieder was gelernt.

In C++ schreibt man dafür aber trotzdem am besten einen Constructor.

Krishty
2011-03-15, 18:18:02
Und in diesem initialisiert man das Array in der Initialisierungsliste mit leeren Klammern, da das Default Initialization bedeutet, die bei PODs immer als Zero Initialization umgesetzt wird. So braucht man dann nicht einmal mehr memset().

(Visual C++ meldet dann u.U. eine ohne Bedenken abschaltbare Kompatibilitätswarnung, da dieses Verhalten, obwohl im Standard vorgeschrieben, afaik erst mit VC2003 eingeführt wurde.)

noid
2011-03-15, 20:00:43
Und in diesem initialisiert man das Array in der Initialisierungsliste mit leeren Klammern, da das Default Initialization bedeutet, die bei PODs immer als Zero Initialization umgesetzt wird. So braucht man dann nicht einmal mehr memset().

(Visual C++ meldet dann u.U. eine ohne Bedenken abschaltbare Kompatibilitätswarnung, da dieses Verhalten, obwohl im Standard vorgeschrieben, afaik erst mit VC2003 eingeführt wurde.)

Naja, Warnungen abschalten ist immer so ne Sache. Und um alle Compiler zufrieden stellen sollte man gleich auch {0,0,0} schreiben.
Zumal ich da nie sicher wäre, dass jeder compiler-provider das wirklich gut gebacken bekommt und dies für alle Ziele wirklich gilt.

Gast
2011-03-16, 00:13:16
Memset ist außerdem nicht ohne Grund eine Stringfunktion. Willst du das was anderes als Nullen in 32 Bit Integers reinschreiben, steht garantiert nicht der gewünschte Wert in deinen Variablen.

Es geht ja auch wirklich nur darum die Struktur mit 0 zu initialisieren und mit keinen anderen Wert. Konstruktor und eine "spezielle" Funktion ist an der Stelle einfach zu aufwändig. Member die anders initialisiert werden müssen kann ich ja direkt über eine Zuweisung initialisieren.

Krishty
2011-03-16, 06:04:18
Naja, Warnungen abschalten ist immer so ne Sache.Es gibt sinnvolle Warnungen, und es gibt weniger sinnvolle. Eine Warnung, weil ein Textteil standardkonform ist (nicht etwa, weil er es nicht ist!), fällt imho in zweite Kategorie.
Und um alle Compiler zufrieden stellen sollte man gleich auch {0,0,0} schreiben.
Zumal ich da nie sicher wäre, dass jeder compiler-provider das wirklich gut gebacken bekommt und dies für alle Ziele wirklich gilt.Wenn er nach über einem Jahrzehnt noch mit Visual C++ 6 oder einer alten Borland-Version kompiliert, ist seine arme Seele eh verloren.

noid
2011-03-16, 07:08:15
Es gibt sinnvolle Warnungen, und es gibt weniger sinnvolle. Eine Warnung, weil ein Textteil standardkonform ist (nicht etwa, weil er es nicht ist!), fällt imho in zweite Kategorie.
Wenn er nach über einem Jahrzehnt noch mit Visual C++ 6 oder einer alten Borland-Version kompiliert, ist seine arme Seele eh verloren.

Ne, die mein ich nicht ;)

Exxtreme
2011-03-16, 09:19:31
Es geht ja auch wirklich nur darum die Struktur mit 0 zu initialisieren und mit keinen anderen Wert. Konstruktor und eine "spezielle" Funktion ist an der Stelle einfach zu aufwändig. Member die anders initialisiert werden müssen kann ich ja direkt über eine Zuweisung initialisieren.
Also 2 zusätzliche Zeilen sind zu aufwändig? :confused:

Und spätestens wenn du das Ding mehrmals anlegst spart ein ordentlicher Konstruktor Zeit da er automatisch initialisiert.

Nighthawk13
2011-03-17, 12:21:33
Gibt vor allem 2 Probleme:
1.) struct/class mit virtuellen Funktionen:
Zumindest bei der memset-Methode wird der vTable-Pointer mit 0 überschrieben, d.h. ein Aufruf einer virtuellen Funktion führt zu einem Crash.
2.) Wenn du später komplexe Datentypen, die einen Konstruktor brauchen(std:string etc) zu dem struct hinzufügen willst, hast du verloren.

Gnafoo
2011-03-17, 14:56:57
Afaik ist in C++ sowieso:


MeineDaten mMydata = {};


die üblichere Variante. Das ruft den Default-Konstruktor für alle Member auf und funktioniert auch für std::string & co. Die Variante {0} würde versuchen das erste Element mit einem passenden Konstruktor zu initialisieren. Wenn dort ein std::string steht, wird z. B. der const-char*-Konstruktor aufgerufen und ein Nullzeiger übergeben.

Zitat aus dem Standard:

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be value-initialized (8.5).



To value-initialize an object of type T means:

if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.



Ein bisschen schlauer als alle Bytes mit 0 zu initialisieren ist die Variante mit „Aggregate Initializer“ schon. Ein Konstruktor ist trotzdem netter, wenn die Klasse/Struktur mehr als nur ein einfacher Datencontainer ist.