2009-04-30 2 views

Antwort

70

Im Gegensatz, was einige in ihren Antworten sagen, ist es ist möglich.

char * c = new char[N](); 

Werden alle Zeichen auf Null initialisiert werden (in Wirklichkeit ist es Wert-Initialisierung bezeichnet. Aber Wert-Initialisierung wird Null-Initialisierung für alle Mitglieder einer Anordnung von skalaren Typ sein). Wenn Sie danach suchen. Es ist nicht irgendeine Erweiterung oder etwas

struct T { int a; }; 
T *t = new T[1](); 
assert(t[0].a == 0); 
delete[] t; 

:

wert zu beachten, dass es auch für (Arrays) Klasse-Typen funktioniert ohne Benutzer Konstruktor deklariert, in welchem ​​Fall ein Mitglied von ihnen Wert initialisiert wird. Es funktionierte und benahm sich in C++ 98 genauso. Genau dort wurde es Standardinitialisierung anstelle der Wertinitialisierung genannt. Die Null-Initialisierung wird jedoch in beiden Fällen für Skalare oder Arrays von Skalar- oder POD-Typen durchgeführt.

+1

Ich lerne jeden Tag etwas Neues aus deinen Beiträgen! Übrigens, weißt du, warum new [N] (42) nicht erlaubt ist? –

+0

T() ist eine spezielle Form: Wert-Initialisierung oder (was es in C++ 98 war) Standard-Initialisierung T (42), ist jedoch direkte Initialisierung und funktioniert nicht für Arrays –

+0

Dies ist das spezifische Szenario Ich habe gesucht, aber all diese anderen Antworten sind auch toll! – nivnad

2

Nein. Es wird immer die zugewiesenen Elemente initialisieren, was im Fall von Primitiven nichts bewirkt. Sie müssen es mit einem Aufruf std :: uninitialized_fill_n oder ähnlichem verfolgen.

0

Nein. Sie müssen den Speicher manuell auf Null setzen. Denken Sie daran, new ist nicht nur zum Reservieren von Speicher, sondern auch zum Initialisieren über Konstruktoren. Hier ist calloc in C praktisch (ohne Initialisierungsfunktionen). Sie können einen Wrapper über new schreiben oder sogar calloc verwenden, aber die meiste Zeit für Nicht-POD-Objekte macht das nicht viel Sinn.

5

Nr Auch denken Sie nicht einmal an so etwas wie tun:

YourClass *var = new YourClass; 
memset(var, 0, sizeof(YourClass)); 

Sie könnten am Ende Ihre VTABLE Wegwerfen (wenn Ihre Klasse hat).

Ich würde empfehlen, Konstruktoren zu verwenden, um den internen Speicher (Variablen) Ihrer Klasse zu löschen.

+3

Ich weiß nicht; Wenn er sich wirklich so sehr in den Fuß schießen will, ist es ethisch, ihn aufzuhalten? :-) –

+0

Definiere deinen Speicher definitiv in deiner Klasse. Verlassen Sie sich nicht auf memset. Es funktioniert in vielen Fällen, aber es ist "undefiniert" in der Spezifikation. –

+0

@McWaffleStic: Netter! :-) –

11

Nein, aber es ist ziemlich einfach, eine neue Version zu erstellen, die wie Calloc funktioniert. Es kann auf die gleiche Weise wie die No-Throw-Version von New durchgeführt werden.

SomeFile.h

struct zeromemory_t{}; 
extern const zeromemory_t zeromemory; 
void* __cdcel operator new(size_t cbSize, const zeromemory_t&); 

SomeFile.cpp

const zeromemory_t zeromemory; 

void* _cdecl operator new(size_t cbSize, const zeromemory_t&) 
{ 
    void *mem = ::operator new(cbSize); 
    memset(mem,0,cbSize); 
    return mem; 
} 

Jetzt können Sie die folgenden, um neue mit zero'd Speicher

MyType* pMyType = new (zeromemory) MyType(); 

Zusätzlich tun würden Sie brauchen andere lustige Dinge zu tun, wie zum Beispiel new [], was auch ziemlich geradlinig ist.

+2

Nur um darauf hinzuweisen, der offizielle Name dafür ist Platzierung neu. Wenn danvin mehr Infos zum Thema wünscht. Kann auch zum Erstellen von Objekt-Caches verwendet werden (denke Linux-Kernel-Platte-Cache) –

+2

s/opeartor/operator /;) Möchten Sie als Warnung setzen, stellen Sie sicher, Instantiate 'const zeromemory_t zeromemory;' in genau einer Übersetzungseinheit. – ephemient

+0

@ephemient, Korrigiert den Rechtschreibfehler. Neugierig, wie könnte der Wert, der nur in einer CPP-Datei definiert ist, in mehr als einer Kompilierungseinheit enthalten sein? – JaredPar

2

Sie könnten eine globale Überladung des Operators new durchführen und sich den Rohspeicher von calloc() holen. Auf diese Weise wird der Speicher gelöscht, bevor Konstruktoren ausgeführt werden können, so dass es dort keine Probleme gibt.

Jede Klasse, die neue selbst außer Kraft setzt, erhält nicht Ihre spezielle calloc()-basierte new, aber dann sollte diese Klasse sich trotzdem korrekt initialisieren.

Vergessen Sie nicht, sowohl new und delete und die Array-Versionen ...

So etwas außer Kraft zu setzen:

#include <exception> // for std::bad_alloc 
#include <new> 
#include <stdlib.h> // for calloc() and free() 

void* operator new (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 


void operator delete (void *p) 
{ 
free(p); 
} 

void* operator new[] (size_t size) 
{ 
void *p=calloc(size, 1); 
if (p==0) // did allocation succeed? 
    throw std::bad_alloc(); 
return p; 
} 

void operator delete[] (void *p) 
{ 
free(p); 
} 

Beachten Sie, dass diese einfachen Versionen sind nicht ganz genau, was sie sein sollten - Der Operator new sollte in einer Schleife ausgeführt werden, die new_handler aufruft (falls eine installiert ist) und nur die bad_alloc Ausnahme auslöst, wenn es keine new_handler gibt. Oder so etwas, ich muss es nachschauen und später aktualisieren.

Oh, und Sie möchten vielleicht auch die no_throw Version überschreiben.

+0

Was passiert mit Klassen, die in diesem Fall virtuelle Methoden definiert haben? –

+1

Es passiert nichts Ungewöhnliches - der Konstruktor wird normal ausgeführt. Es ist nur so, dass der rohe Speicher, an dem der Konstruktor arbeitet, immer gelöscht wurde. –

0

Wenn Sie nicht darauf bestehen, new zu verwenden, können Sie einfach Vektor: vector<char> buffer; buffer.resize(newsize); verwenden und der Inhalt wird auf Null gesetzt.

0

Ja.

int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5 

Für Arrays können Sie etwas wie memset verwenden. Verwenden Sie für Windows ZeroMemory oder SecureZeroMemory.

Bearbeiten: Bitte sehen Sie @ Litb's Beitrag, er zeigt, wie Sie auf 0 für Arrays mit nicht direkten Initialisierung wie oben initialisieren können.

+0

versuchen mit Array - es wird nicht funktionieren (zumindest für ISO C++ - vielleicht erlauben einige Compiler mit Erweiterung es). – Francis

0
class MyClass { 
    public: 
    void* operator new(size_t bytes) { 
     return calloc(bytes, 1); 
    } 
} 

Und Sie können den globalen neuen Operator überschreiben, wenn Sie möchten.

0

können Sie sagen:

vector <char> v(100, 0); 

, die eine zusammenhängende Reihe von 100 Zeichen schafft neue Verwendung und initialisiert sie alle zu Null. Sie können dann auf das Array mit Vektor der Operator [], oder indem Sie:

char * p = &v[0]; 
p[3] = 42; 

Hinweis: dieser befreit Sie auch anrufen zu müssen löschen den zugewiesenen Speicher freizugeben.

1

i verwenden, um ein Makro:

#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE(); 

es zu benutzen:

Whatever* myWhatever = newclear(Whatever); 

(diese verwendet "Platzierung neue" wie einige andere Lösungen hier)

+0

vergiss nicht das # vor define: D (scheinbar entfernt diese Seite es. –

+2

gibt es eigentlich eine spezielle Formatierung für Quellcode. Alles was du einrückst Vier Leerzeichen erhalten die spezielle Hervorhebung (siehe meine Bearbeitung). –

Verwandte Themen