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
den Speicher nicht mit Nullen initialisiert. Aber hier scheint es so zu sein. Wie funktioniert es?
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 Kommentar unten.
Ehm ... bist du sicher, dass
new unsigned int[5]()
die ganzen Zahlen auf Null setzt?
Anscheinend ja:
[C++ 11: 5.3.4/15]: Ein neuer Ausdruck, der ein Objekt vom Typ T erstellt, initialisiert dieses Objekt wie folgt: Wenn der Neuinitialisierer weggelassen wird, wird das Objekt standardmäßig initialisiert (8.5). Wird keine Initialisierung durchgeführt, hat das Objekt einen unbestimmten Wert. Andernfalls wird der Neuinitialisierer gemäß den Initialisierungsregeln von 8.5 für die Direktinitialisierung interpretiert.
#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
>
Es ist nicht garantiert, dass operator new
Den Speicher für irgendetwas initialisiert, und der neuer Ausdruck, der einen unsigned int
Ohne neuer Initialisierer zuweist, verlässt den Objekt mit einem unbestimmten Wert.
Das Lesen des Werts eines nicht initialisierten Objekts führt zu ndefiniertes Verhalten. ndefiniertes Verhalten Umfasst das Auswerten auf den Wert Null ohne negative Auswirkungen, kann jedoch dazu führen, dass etwas passiert, sodass Sie vermeiden sollten, dass es verursacht wird.
In C++ 11 wird die Sprache verwendet, in der die zugewiesenen Objekte default-initialized lauten, was bedeutet, dass bei Nicht-Klassentypen keine Initialisierung durchgeführt wird. Dies unterscheidet sich von der Bedeutung von default-initialized in C++ 03.
Bei einigen Compilern initialisiert die Debug-Version von new die Daten, aber Sie können sich auf nichts verlassen.
Es ist auch möglich, dass der Speicher gerade 0 von einer vorherigen Verwendung hatte. Gehen Sie nicht davon aus, dass zwischen delete und new nichts mit dem Speicher passiert ist. Es könnte etwas im Hintergrund 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 auf eine ganz andere Position als zuvor abgebildet.
Fazit: Wenn Sie einen Speicherort nicht speziell initialisiert haben, können Sie nichts über dessen Inhalt annehmen. Der Speichermanager weist möglicherweise nicht einmal einen bestimmten physischen Speicherort zu, bis Sie den Speicher verwenden.
Moderne Speicherverwaltung ist erstaunlich komplex, aber als C++ - Programmierer ist es Ihnen eigentlich egal (meistens ‡). Halten Sie sich an die Regeln und Sie werden keinen Ärger bekommen.
‡ Es könnte Sie interessieren, ob Sie optimieren, um Seitenfehler zu reduzieren.
Das ist nicht operator new
, das ist der Operator new
. Es gibt tatsächlich einen großen Unterschied! Der Unterschied ist, dass operator new
ist eine Funktion, die unformatierten Speicher zurückgibt. Wenn Sie den Operator new
verwenden, wird ein Konstruktor für Sie aufgerufen. Es ist der Konstruktor, der den Wert dieses int
festlegt, nicht operator new
.