Gibt es einen Anruf, den ich an new
machen kann, um Speicher wie calloc
zu löschen?C++: neuer Anruf, der sich wie Calloc verhält?
Antwort
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.
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.
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.
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.
Ich weiß nicht; Wenn er sich wirklich so sehr in den Fuß schießen will, ist es ethisch, ihn aufzuhalten? :-) –
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. –
@McWaffleStic: Netter! :-) –
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.
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) –
s/opeartor/operator /;) Möchten Sie als Warnung setzen, stellen Sie sicher, Instantiate 'const zeromemory_t zeromemory;' in genau einer Übersetzungseinheit. – ephemient
@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
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.
Was passiert mit Klassen, die in diesem Fall virtuelle Methoden definiert haben? –
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. –
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.
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.
versuchen mit Array - es wird nicht funktionieren (zumindest für ISO C++ - vielleicht erlauben einige Compiler mit Erweiterung es). – Francis
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.
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.
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)
vergiss nicht das # vor define: D (scheinbar entfernt diese Seite es. –
gibt es eigentlich eine spezielle Formatierung für Quellcode. Alles was du einrückst Vier Leerzeichen erhalten die spezielle Hervorhebung (siehe meine Bearbeitung). –
- 1. C++: Funktionswrapper, der sich genau wie die Funktion selbst verhält
- 2. C++: Schleife verhält sich nach Steueranweisung anders
- 3. Wie verhält sich dieser XPath?
- 4. usort verhält sich nicht wie
- 5. Wie verhält sich rsync beim gleichzeitigen Dateizugriff?
- 6. Serieller Port empfängt Thread, der sich nicht erwartungsgemäß verhält - C++
- 7. Generator verhält sich nicht wie erwartet
- 8. z-Index verhält sich nicht wie ich
- 9. Jquery verhält sich anders
- 10. Zsh verhält sich seltsam
- 11. Bash-Skript, das sich wie Makefile verhält
- 12. C# Vererbung verhält sich nicht so, wie ich es erwarte
- 13. C# WCF verhält sich wie eine einzelne Benutzerinstanz
- 14. Warum verhält sich ref in C++ 0x nicht wie erwartet?
- 15. Regex Split verhält sich nicht wie erwartet
- 16. Task.Delay() verhält sich nicht wie erwartet
- 17. Suche nach einem Ninject-Bereich, der sich wie InRequestScope verhält
- 18. Type.IsSubclassOf verhält sich nicht wie erwartet
- 19. img verhält sich wie ein Hintergrund img?
- 20. UITableViewRowAnimationNone - verhält sich wie UITableViewRowAnimation (Top/Bottom)
- 21. SSLContext Schein verhält sich nicht wie erwartet
- 22. Make index.php verhält sich wie ein Verzeichnis
- 23. Warum verhält sich TFormatSettings nicht wie erwartet?
- 24. Wie verhält sich DataContractJsonSerializer auf WP7?
- 25. Die $ HTTP_REFERER verhält sich wie die $ DOCUMENT_URI
- 26. Fibonacci-Sequenzimplementierung verhält sich nicht wie erwartet
- 27. Lodash DifferenceBy verhält sich nicht wie excepted
- 28. cakephp - Sitzungsvariable verhält sich merkwürdig
- 29. PHP empty() verhält sich seltsamerweise
- 30. PHP 'addslashes' verhält sich nicht wie erwartet
Ich lerne jeden Tag etwas Neues aus deinen Beiträgen! Übrigens, weißt du, warum new [N] (42) nicht erlaubt ist? –
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 –
Dies ist das spezifische Szenario Ich habe gesucht, aber all diese anderen Antworten sind auch toll! – nivnad