Ich fange gerade erst an, in C ++ einzusteigen, und ich möchte einige gute Gewohnheiten aufgreifen. Wenn ich int
dem new
Operator gerade ein Array vom Typ zugewiesen habe , wie kann ich sie alle auf 0 initialisieren, ohne sie alle selbst zu durchlaufen? Soll ich nur verwenden memset
? Gibt es eine "C ++" - Möglichkeit, dies zu tun?
c++
initialization
memory-management
new-operator
Dreamlax
quelle
quelle
&vector[0]
.Antworten:
Es ist eine überraschend wenig bekannte Funktion von C ++ (was durch die Tatsache belegt wird, dass dies noch niemand als Antwort gegeben hat), aber es hat tatsächlich eine spezielle Syntax für die Wertinitialisierung eines Arrays:
Beachten Sie, dass Sie müssen die leeren Klammern verwenden - Sie können nicht, zum Beispiel, die Verwendung
(0)
oder irgendetwas anderes (weshalb diese für Wert Initialisierung nur dann sinnvoll ist).Dies ist ausdrücklich in ISO C ++ 03 5.3.4 [expr.new] / 15 zulässig, in dem es heißt:
und schränkt die Typen, für die dies zulässig ist, nicht ein, während das
(expression-list)
Formular durch weitere Regeln im selben Abschnitt explizit eingeschränkt wird, sodass keine Array-Typen zulässig sind .quelle
new int[10] {}
. Sie können auch Wertenew int[10] {1,2,3}
Angenommen, Sie möchten wirklich ein Array und keinen std :: vector, dann wäre dies der "C ++ - Weg"
Beachten Sie jedoch, dass dies unter der Haube eigentlich immer noch nur eine Schleife ist, die jedes Element 0 zuweist (es gibt wirklich keine andere Möglichkeit, dies zu tun, außer einer speziellen Architektur mit Unterstützung auf Hardwareebene).
quelle
Es gibt eine Reihe von Methoden, um ein Array vom intrinsischen Typ zuzuweisen, und alle diese Methoden sind korrekt, obwohl die Auswahl ...
Manuelle Initialisierung aller Elemente in der Schleife
Verwenden der
std::memset
Funktion von<cstring>
Verwenden des
std::fill_n
Algorithmus von<algorithm>
Mit
std::vector
ContainernWenn C ++ 0x verfügbar, mit Initialisiererliste Funktionen
quelle
int array[SIZE] ={1,2,3,4,5,6,7};
Notation verwendenvoid rotateArray(int (& input)[SIZE], unsigned int k);
würde, könnte ich meine Funktionsdeklaration verwenden. Was wäre, wenn ich die erste Konvention verwenden würde? irgendein Vorschlag?std::memset
ist falsch - Sie übergeben 10, es scheint die Anzahl der Bytes zu erwarten - siehe en.cppreference.com/w/cpp/string/byte/memset . (Ich denke, dies zeigt sehr gut, warum man ein solches Konstrukt auf niedriger Ebene nach Möglichkeit vermeiden sollte.)Wenn der Speicher, den Sie zuweisen, eine Klasse mit einem Konstruktor ist, der etwas Nützliches tut, ruft der Operator new diesen Konstruktor auf und lässt Ihr Objekt initialisiert.
Wenn Sie jedoch einen POD oder etwas zuweisen, das keinen Konstruktor hat, der den Status des Objekts initialisiert, können Sie keinen Speicher zuweisen und diesen Speicher mit dem in einer Operation neuen Operator initialisieren. Sie haben jedoch mehrere Möglichkeiten:
1) Verwenden Sie stattdessen eine Stapelvariable. Sie können in einem Schritt wie folgt zuweisen und standardmäßig initialisieren :
2) verwenden
memset()
. Beachten Sie, dass wenn das Objekt, das Sie zuweisen, kein POD ist , es eine schlechte Idee ist, es zu speichern. Ein spezielles Beispiel ist, wenn Sie eine Klasse mit virtuellen Funktionen memseten, die vtable wegblasen und Ihr Objekt in einem unbrauchbaren Zustand belassen.3) Viele Betriebssysteme haben Aufrufe, die das tun, was Sie wollen - auf einem Heap zuweisen und die Daten für etwas initialisieren. Ein Windows-Beispiel wäre
VirtualAlloc()
4) Dies ist normalerweise die beste Option. Vermeiden Sie es, den Speicher selbst zu verwalten. Sie können STL-Container verwenden, um fast alles zu tun, was Sie mit Rohspeicher tun würden, einschließlich der Zuweisung und Initialisierung auf einen Schlag:
quelle
Ja da ist:
Verwenden Sie einen Vektor anstelle eines dynamisch zugewiesenen Arrays. Zu den Vorteilen gehört, dass Sie sich nicht darum kümmern müssen, das Array explizit zu löschen (es wird gelöscht, wenn der Vektor den Gültigkeitsbereich verlässt), und dass der Speicher automatisch gelöscht wird, selbst wenn eine Ausnahme ausgelöst wird.
Bearbeiten: Um weitere Drive-by-Abstimmungen von Personen zu vermeiden, die sich nicht die Mühe machen, die folgenden Kommentare zu lesen, sollte ich klarer machen, dass diese Antwort nicht besagt, dass der Vektor immer die richtige Antwort ist. Aber es ist sicher mehr C ++ als "manuell", um sicherzustellen, dass ein Array gelöscht wird.
Mit C ++ 11 gibt es jetzt auch std :: array, das ein Array mit konstanter Größe modelliert (gegenüber einem Vektor, der wachsen kann). Es gibt auch std :: unique_ptr, das ein dynamisch zugewiesenes Array verwaltet (das mit der Initialisierung kombiniert werden kann, wie in anderen Antworten auf diese Frage beantwortet). All dies ist eine C ++ - Methode, als den Zeiger auf das Array IMHO manuell zu handhaben.
quelle
std::vector
anstelle von dynamisch zugewiesenen Arrays verwenden? Was sind die Vorteile der Verwendung eines Arrays gegenüber einem Vektor und umgekehrt?std::vector
.vector
überall unabhängig vom Kontext ist „Schreiben von Java - Code in C ++“ bezeichnet.std::fill
ist eine Möglichkeit. Benötigt zwei Iteratoren und einen Wert, mit dem die Region gefüllt wird. Das oder die for-Schleife wäre (ich nehme an) der C ++ - Weg.Das Festlegen eines Arrays primitiver Ganzzahltypen auf 0
memset
ist in Ordnung, kann jedoch die Augenbrauen hochziehen. Bedenken Sie auchcalloc
, obwohl die Verwendung von C ++ aufgrund der Besetzung etwas unpraktisch ist.Ich für meinen Teil benutze so ziemlich immer eine Schleife.
(Ich mag es nicht, die Absichten der Leute zu hinterfragen, aber es ist wahr, dass
std::vector
alle Dinge gleich sind und der Verwendung vorzuziehen sindnew[]
.)quelle
Sie können immer memset verwenden:
quelle
memset
, aber ich war mir nicht sicher, ob dies der C ++ - Weg war, um das Problem anzugehen.10 * sizeof( *myArray )
ist dokumentierter und veränderungssicherer als10 * sizeof( int )
.In der Regel verwenden Sie für dynamische Listen von Elementen a
std::vector
.Im Allgemeinen verwende ich ein Memset oder eine Schleife für die dynamische Zuweisung des Rohspeichers, je nachdem, wie variabel dieser Codebereich in Zukunft sein wird.
quelle