Es gibt einen solchen Code:
#include <iostream>
int main(){
unsigned int* wsk2 = new unsigned int(5);
std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
delete wsk2;
wsk2 = new unsigned int;
std::cout << "wsk2: " << wsk2 << " " << *wsk2 << std::endl;
return 0;
}
Ergebnis:
wsk2: 0x928e008 5
wsk2: 0x928e008 0
Ich habe gelesen, dass new
der Speicher nicht mit Nullen initialisiert wird. Aber hier scheint es so. Wie funktioniert es?
c++
memory-management
scdmb
quelle
quelle
Antworten:
Es gibt zwei Versionen:
wsk = new unsigned int; // default initialized (ie nothing happens) wsk = new unsigned int(); // zero initialized (ie set to 0)
Funktioniert auch für Arrays:
wsa = new unsigned int[5]; // default initialized (ie nothing happens) wsa = new unsigned int[5](); // zero initialized (ie all elements set to 0)
Als Antwort auf den Kommentar unten.
Anscheinend schon:
#include <new> #include <iostream> int main() { unsigned int wsa[5] = {1,2,3,4,5}; // Use placement new (to use a know piece of memory). // In the way described above. // unsigned int* wsp = new (wsa) unsigned int[5](); std::cout << wsa[0] << "\n"; // If these are zero then it worked as described. std::cout << wsa[1] << "\n"; // If they contain the numbers 1 - 5 then it failed. std::cout << wsa[2] << "\n"; std::cout << wsa[3] << "\n"; std::cout << wsa[4] << "\n"; }
Ergebnisse:
> g++ --version Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) Target: x86_64-apple-darwin13.2.0 Thread model: posix > g++ t.cpp > ./a.out 0 0 0 0 0 >
quelle
new/new[]
Betreibern? Wirdnew unsigned int[5]()
das Array auch dann noch auf Null initialisiert, wenn es eine proprietäre, völlig unabhängige Implementierung hat?operator new
ist eine vom Benutzer (Entwickler) definierte Funktion, die beliebig ausgeführt werden kann. Der Standard schränkt die Funktionsweise dieser Funktion nicht ein. Genauso wie eroperator==
alles tun kann, was der Benutzer definiert (er muss nicht einmal bool zurückgeben, geschweige denn auf Gleichheit testen (obwohl es eine schlechte Form ist, wenn dies nicht der Fall ist)).()
Syntax wird der Puffer ohne Beziehung zum Typ des zugewiesenen Objekts und seinen Konstruktoren mit Null initialisiert . (Und ich nehme an, C ++ 11 ändert nichts an diesem Aspekt)8.3.4 New
. Warum wurde es geändert. Weil wir die Wertinitialisierung erzwingen. Siehe11.6 Initializers
. Beachten Sie, dass wir einen Zeiger auf den neuen Operator übergeben. Der Wert vonwsa
wird NICHT geändert. Es wird die Adresse geändert, auf die verwiesen wird.operator new
Es wird nicht garantiert, dass der Speicher für irgendetwas initialisiert wird, und der neue Ausdruck , der einenunsigned int
ohne einen neuen Initialisierer zuweist, hinterlässt dem Objekt einen unbestimmten Wert.Das Lesen des Werts eines nicht initialisierten Objekts führt zu undefiniertem Verhalten . Undefiniertes Verhalten umfasst das Auswerten auf den Wert Null ohne negative Auswirkungen, kann jedoch dazu führen, dass etwas passiert. Sie sollten daher vermeiden, es zu verursachen.
In C ++ 11 wird als Sprache verwendet, dass die zugewiesenen Objekte standardmäßig initialisiert werden, was für Nichtklassentypen bedeutet, dass keine Initialisierung durchgeführt wird. Dies unterscheidet sich von der Bedeutung der Standardinitialisierung in C ++ 03.
quelle
Bei einigen Compilern initialisiert die Debug-Version von new die Daten, aber es gibt sicherlich nichts, auf das Sie sich verlassen können.
Es ist auch möglich, dass der Speicher gerade 0 aus einer früheren Verwendung hatte. Gehen Sie nicht davon aus, dass zwischen Löschen und Neu nichts mit dem Speicher passiert ist. Im Hintergrund könnte etwas geschehen, das Sie nie bemerkt haben. Außerdem ist derselbe Zeigerwert möglicherweise nicht derselbe physische Speicher. Speicherseiten werden verschoben und ausgelagert. Ein Zeiger wird möglicherweise einer ganz anderen Position als zuvor zugeordnet.
Fazit: Wenn Sie einen Speicherort nicht speziell initialisiert haben, können Sie nichts über dessen Inhalt annehmen. Der Speichermanager weist möglicherweise erst dann einen bestimmten physischen Speicherort zu, wenn Sie den Speicher verwenden.
Die moderne Speicherverwaltung ist erstaunlich komplex, aber als C ++ - Programmierer ist Ihnen das eigentlich egal (meistens ‡). Spielen Sie nach den Regeln und Sie werden keine Probleme bekommen.
‡ Es könnte Sie interessieren, ob Sie optimieren, um Seitenfehler zu reduzieren.
quelle
Das ist nicht
operator new
, das ist dernew
Betreiber. Es gibt tatsächlich einen großen Unterschied! Der Unterschied besteht darin, dassoperator new
es sich um eine Funktion handelt, die Rohspeicher zurückgibt. Wenn Sie dennew
Operator verwenden, wird ein Konstruktor für Sie aufgerufen. Es ist der Konstruktor, der den Wert davon festlegtint
, nichtoperator new
.quelle