2012-09-27 3 views
20

Warum ist es nicht möglich, die Länge eines Puffers auf diese Weise zu erhalten.Größe des dynamisch zugewiesenen Arrays finden

AType * pArr = new AType[nVariable]; 

Wenn das gleiche Array

delete [] pArr; 

die Laufzeit freigegeben wird wissen muss, wie viel freizugeben. Gibt es eine Möglichkeit, auf die Länge zuzugreifen, bevor das Array gelöscht wird? Wenn nein, warum wird keine solche API bereitgestellt, die die Länge abruft?

+1

Ausgezeichnete Frage +1 –

+0

Der beste Weg ist zu verwenden, 'std :: vector pArr (nVariable);'. Dies wird intern mit dynamischer Zuweisung zugewiesen und Sie haben '.size()' immer praktisch. – iammilind

+1

[C++ FAQ-Eintrag zu diesem.] (Http://www.parashift.com/c++-faq-lite/num-elems-in-new-array.html) – jrok

Antwort

4

Gibt es eine Möglichkeit, auf die Länge zuzugreifen, bevor das Array gelöscht wird?

Nein, es gibt keine Möglichkeit, das festzustellen.
Der Standard erfordert nicht, dass sich die Implementierung an die Spezifizierung der Anzahl der Elemente erinnert, die über new angefordert werden.
Die Implementierung kann einfach bestimmte Bitmuster am Ende zugewiesener Speicherblöcke einfügen, statt sich die Anzahl der Elemente zu merken, und könnte einfach nach dem Muster suchen, während es den Speicher freigibt.
Kurz gesagt, es ist nur eine Erläuterung Detail.


Auf einer Seite zur Kenntnis, gibt es 2 Möglichkeiten praktisch, dieses Problem zu überwinden:

  1. Sie können einfache Nutzung ein std::vector, die Sie Elementfunktionen wie size() oder
  2. Sie einfach liefert kann Führen Sie die Buchhaltung selbst aus.

newatleast weist genügend Speicher so viel wie Sie verlangten.
Sie wissen bereits, wie viel Speicher Sie angefordert haben, damit Sie die Länge leicht berechnen können. Sie können die Größe jedes Artikels mit sizeof finden.

Total memory requested/Memory required for 1 item = No of Items 
+0

Dieser downovte ist, weil ...? –

+3

Ich habe Sie nicht abgelehnt, aber ich denke, das Problem ist, dass er fragt, warum der Standard das nicht bietet, und Sie sagen, dass es so ist, weil der Standard das sagt. Er fragt nach einer Begründung, nicht nach einer Lösung eines konkreten Problems. – akappa

+0

@akappa: Meine Antwort gibt die Begründung, es kann effektive/bessere Möglichkeiten geben, wie eine Implementierung den zugewiesenen Speicher verfolgen kann, und daher zwingt der Standard die Implementierungen nicht dazu, dies auf eine bestimmte Weise zu tun. Tatsächlich die Antwort sagt sogar einen solchen Weg. Da du sagst, das ist keine Begründung, bitte erleuchte mich darüber, wie/warum denkst du, das ist keine Begründung? –

5

Die Laufzeit weiß, wie viel zugeteilt wurde. Solche Details sind jedoch compilerspezifisch, so dass Sie keine plattformübergreifende Möglichkeit haben, damit umzugehen.

Wenn Sie die gleiche Funktionalität wie und in der Lage sein, die Größe verfolgen Sie eine std :: vector verwenden könnte wie folgt:

std::vector<AType> pArr(nVariable); 

Dies hat den zusätzlichen Vorteil, auch mit RAII.

+0

Ich stimme zu, dass die Implementierung compilerspezifisch ist. Aber was hält den Standard davon ab, C++ - Anbieter aufzufordern, eine API wie die unten angegebene bereitzustellen. size_t array_sizeof (void const * pHead); – Ram

+0

@Ram: Ich weiß nicht, was den Standard davon abhält zu fragen, wie viele Laufzeiten es erlauben. Es kann einen Weg geben, um Zuweisungen zu implementieren, für die es nicht möglich ist, und das ist der Grund dafür, es nicht aufzudecken. Ich kann jedoch nicht von einem Zuweisungsmuster denken, für das Sie es nicht tun könnten ... – Goz

+0

@Ram: Persönlich verwende ich immer Vektoren anstelle der dynamischen Zuordnung für die Vorteile von RAII, kopieren Semantik und Größe zu verfolgen. – Goz

2

Nein, nicht wirklich. Zumindest nicht in einer plattformunabhängigen, definierten Weise.

Die meisten Implementierungen speichern jedoch die Größe eines dynamisch zugewiesenen Arrays vor dem eigentlichen Array.

+3

Wirklich. Die, die ich gesehen habe, tun es nicht. –

+0

@ JamesKanze MSVS sicherlich. –

+0

Ich habe es gerade mit VC10 versucht. Wenn ich 'new char [10]' tue, enthält 'size_t' direkt vor dem zurückgegebenen Zeiger' 917978'. (Bei g ++ enthält es '17', was tatsächlich mit der Menge des zugewiesenen Speichers zusammenhängen kann, da Ausrichtungsbetrachtungen den Betrag auf das nächste Vielfache von 8 runden müssen.) –

3

Der Operator delete muss die Größe nicht kennen, um den zugewiesenen Speicher freizugeben, genauso wie der Systemaufruf free nicht funktioniert. Dies liegt daran, dass dieses Problem dem Betriebssystem und nicht dem Compilers-Laufzeitsystem überlassen wird.

+1

Nicht wirklich, lösche Operation und die freie Bibliotheksfunktion muss das wissen.Ich denke, viele Implementierungen geben dem Betriebssystem keinen Heapspeicher zurück, sondern verwenden ihn wieder, und selbst wenn sie Speicher zurückgeben, gibt es keine 1: 1-Zuordnung zwischen dem Aufruf von free/delete und einem Systemaufruf, der Speicher zurückgibt (weil OS In der Regel wird es Ihnen nicht möglich sein, Speicher in kleinen Blöcken zurückzugeben, sondern multipliziert mit einer Seitengröße. –

+1

zumindest für Nicht-POD-Datentypen die Laufzeit muss es wissen, da es die Dtors aufrufen muss. Für POD-Datentypen ist es sicher zu sagen, dass die C++ - RTS möglicherweise weiß, wie viel Speicherplatz zugewiesen wurde, da die Handhabung von freiem Speicher außerhalb des Standards liegt. – akappa

3

Die Laufzeitumgebung muss die gleiche Menge freigeben, wie sie zugewiesen wurde, und sie behält dies in gewisser Weise (normalerweise sehr indirekt) bei. Aber gibt es keine zuverlässige Möglichkeit, von der Menge zu Elemente zugewiesen zu bekommen: die Menge zugewiesen kann nicht weniger sein als die Anzahl der Elemente mal die Größe jedes Elements, aber es wird oft mehr sein. Ausrichtung Überlegungen, zum Beispiel bedeuten, dass new char[5] und new char[8] oft die gleiche Menge an Speicher zuweisen, und es gibt verschiedene Zuordnungsstrategien, die erheblich mehr Speicher zugeordnet werden kann, was unbedingt erforderlich ist.

0

warum nicht ein bisschen mehr Informationen wie folgt aus:

template <typename T> class AType 
{ 
public: 

    AType(size_t s) : data(0) 
    { 
     a_size = s; 
     data = new T[s]; 
    } 
    ~AType() { 
     if (data != nullptr) 
      delete [] data; 
    } 

    size_t getSize() const 
    { 
     return a_size * sizeof(T); 
    } 

private: 
    size_t a_size; 
    T* data; 
}; 
1

Es gibt keine tragbare Art und Weise in C++ die Größe eines dynamisch zugewiesenen Array aus dem rohen Zeiger zu erhalten.

Unter MSVC und WIN32 können Sie die Größe des zugewiesenen Blocks mit der Funktion _msize (void *) abrufen.

siehe https://msdn.microsoft.com/en-us/library/z2s077bc.aspx für weitere Details.