2010-03-09 1 views
18

Wenn Sie ein Array mit new [] zuweisen, warum können Sie nicht die Größe des Arrays aus dem Zeiger herausfinden? Es muss zur Laufzeit bekannt sein, sonst würde delete [] nicht wissen wieviel Speicher frei ist.Warum ist es nicht möglich, auf die Größe eines neuen Arrays zuzugreifen?

Es sei denn, ich vermisse etwas?

+0

Ein einfaches, gutes Design muss es nicht wissen - in einem komplexen Fall muss man viel selbst verwalten. Es gibt im Allgemeinen Debug-Funktionen für Ihren Compiler, die Ihnen sagen werden - aber wenn Sie das brauchen, ist Ihr Design wahrscheinlich falsch. –

+0

Ich habe mich oft gewundert, warum Sie nie einen Zuordner sehen, der die Größe nicht kennt und verlangt, dass er beim Löschen weitergegeben wird. Denn wie oft sind Sie jemals gekommen, um einen Speicherblock zu löschen und nicht in der Lage, seine Größe zu berechnen? Ich denke, es hätte nie wirklich einen Vorteil für die Implementierung eines Systems mit dieser Einschränkung geben können ... – matt

+0

Es würde wahrscheinlich unnötige Einschränkungen bei der Implementierung einer solchen Low-Level-Operation geben. Nach allem, was Sie wissen, wie viel Sie gefragt haben, wenn Sie das Array zugewiesen, so gibt es keine dringende Notwendigkeit der Laufzeit, um Ihnen das sagen zu können. – UncleBens

Antwort

14

In einer typischen Implementierung ist die Größe des dynamischen Speicherblocks irgendwie im Block selbst gespeichert - das ist richtig. Aber es gibt keinen Standardweg, um auf diese Informationen zuzugreifen. (Implementierungen können implementierungsspezifische Möglichkeiten bieten, um darauf zuzugreifen). So ist es mit malloc/free, so ist es mit new[]/delete[].

In der Tat, in einer typischen Implementierung roher Speicherzuordnungen für new[]/delete[] Anrufe werden schließlich durch ein implementierungsspezifische malloc/free -ähnlichen Paare verarbeitet werden, was bedeutet, dass delete[] nicht wirklich kümmern hat, wie vielen Speicher freizugeben: es einfach ruft das interne free (oder wie auch immer es heißt), das kümmert sich darum.

Was delete[] muss allerdings wissen, ist, wie viele Elemente Destruct in Situationen, in denen Array Elementtyp nicht-trivial destructor hat. Und das ist, worum geht es bei Ihrer Frage - die Anzahl der Array-Elemente, nicht die Größe des Blocks (diese beiden sind nicht gleich, der Block könnte größer sein als wirklich für das Array selbst erforderlich). Aus diesem Grund wird die Anzahl der Elemente in dem Array normalerweise auch innerhalb des Blocks durch new[] gespeichert und später durch delete[] abgerufen, um die richtige Arrayelementzerstörung durchzuführen. Es gibt auch keine Standardmethoden, um auf diese Nummer zuzugreifen.

(Dies bedeutet, dass im allgemeinen Fall ein typischer Speicherblock durch new[] zugeordnet unabhängig wird, gleichzeitig speichern sowohl die physikalische Blockgrße in Bytes und die Array-Elemente Zahl. Diese Werte, die durch verschiedene Ebene der C gespeichert sind ++ Speicherzuweisungsmechanismus - Raw Memory Allocator und new[] selbst - und interagieren nicht in irgendeiner Weise miteinander.

Beachten Sie jedoch, dass die Anzahl der Array-Elemente aus den oben genannten Gründen normalerweise nur dann gespeichert wird, wenn der Array-Elementtyp einen nicht-trivialen Destruktor aufweist. I.e. Diese Anzahl ist nicht immer vorhanden. Dies ist einer der Gründe, warum es nicht machbar ist, eine Standardmethode für den Zugriff auf diese Daten bereitzustellen: Sie müssen sie entweder immer speichern (was Speicher verschwendet) oder ihre Verfügbarkeit nach Destruktor-Typ einschränken (was verwirrend ist).

die oben Zur Veranschaulichung, wenn Sie eine Reihe von int s

int *array = new int[100]; 

der Größe des Arrays (dh 100) erstellen, ist nicht normalerweise durch new[] da delete[] gespeichert überhaupt nicht darum kümmern (int hat keinen Destruktor). Die physische Größe des Blocks in Bytes (wie 400 Bytes oder mehr) wird normalerweise in dem Block durch den Rohspeicherzuordner gespeichert (und von dem durch delete[] aufgerufenen Raw-Speicherfreigabeverteiler verwendet), aber für einige kann er leicht 420 sein implementierungsspezifischer Grund. Daher ist diese Größe für Sie im Grunde genommen nutzlos, da Sie nicht die genaue ursprüngliche Array-Größe daraus ableiten können.

+1

Ja, der Speicherzuordner kennt die Größe des Arrays möglicherweise nicht, möglicherweise hat er einen Block der nächstgrößeren verfügbaren Größe zurückgegeben, und es interessiert Sie nicht einmal, dass Sie nur 75% davon verwendet haben es. –

7

Sie können höchstwahrscheinlich darauf zugreifen, aber es würde eine genaue Kenntnis Ihres Zuordners erfordern und wäre nicht portabel. Der C++ - Standard spezifiziert nicht , wie Implementierungen diese Daten speichern, so gibt es keine konsistente Methode, um es zu erhalten. Ich glaube, es ist nicht spezifiziert, weil verschiedene Zuordner es aus Gründen der Effizienz möglicherweise auf unterschiedliche Weise speichern möchten.

+0

Dennoch wäre es cool gewesen, wenn der Standard einen 'len (...)' -Operator angegeben hätte, also ist es möglich, die Größe eines Arrays mit diesem Operator zu ermitteln (und die Autoren können diesen len-Operator wie gewünscht implementieren). .. :( – smerlin

+4

@smelin Ist nicht das, wofür 'std :: vector <>' ist? – KitsuneYMG

5

Dies ist sinnvoll, da z. B. die Größe des zugewiesenen Blocks nicht notwendigerweise die gleiche Größe wie das Array haben muss. Während it is true, dass new[] die Anzahl der Elemente speichern kann (Aufruf jedes Elements Destruktor), muss es nicht, wie es für einen leeren Destruktor nicht erforderlich wäre. Es gibt auch keinen Standardweg (C++ FAQ Lite 1, C++ FAQ Lite 2) der Implementierung, wobei new[] die Array-Länge speichert, da jede Methode ihre Vor- und Nachteile hat.

Mit anderen Worten, es ermöglicht Zuweisungen zu so schnell und billig wie möglich, indem Sie nichts über die Implementierung angeben. (Wenn die Implementierung die Größe des Arrays sowie die Größe des zugewiesenen Blocks jedes Mal speichern muss, wird Speicher verschwendet, den Sie möglicherweise nicht benötigen).

3

Einfach ausgedrückt, der C++ - Standard erfordert keine Unterstützung dafür. Es ist möglich, dass, wenn Sie genug über die Interna Ihres Compilers wissen, Sie herausfinden können, wie man auf diese Informationen zugreift, aber das würde allgemein als schlechte Praxis betrachtet werden. Beachten Sie, dass das Speicherlayout für Heap-allocated Arrays und Stack-allocated arrays unterschiedlich sein kann.

dass Denken Sie daran, im Wesentlichen, was Sie reden hier sind C-Stil-Arrays, auch - obwohl new und delete sind C++ Operatoren - und das Verhalten von C. vererbt Wenn Sie eine C++ wollen „Array“, das heißt Größe sollten Sie die STL verwenden (zB std :: vector, std :: deque).

+0

Ja, ich benutze normalerweise keine C-artigen Arrays - es war nur eine allgemeine Frage (wenn es so wäre möglich) spart in einigen Fällen etwas Speicher –