Unterschied zwischen char[] und char neu[] bei der Verwendung von Konstanten Längen
Also dies mag wie ein weit-beantwortete Frage, aber ich interessiere mich mehr in die Interna, was genau passiert, anders zwischen den beiden.
Andere als die Tatsache, dass im zweiten Beispiel wird nicht nur das Gedächtnis, sondern einen Zeiger auf den Speicher, was passiert im Speicher, wenn Folgendes passiert:
char a[5];
char b* = new char[5];
Mehr direkt mit warum ich fragte diese Frage, wie kommt es, dass ich tun kann,
const int len = 5;
char* c = new char[len];
aber nicht
const int len = 5;
char d[len]; //Compiler error
BEARBEITEN Sollte erwähnt haben, ich bin immer dieser compiler Fehler auf VC++ (go figure...)
1>.\input.cpp(138) : error C2057: expected constant expression
1>.\input.cpp(138) : error C2466: cannot allocate an array of constant size 0
1>.\input.cpp(138) : error C2133: 'd' : unknown size
EDIT 2: Soll gebucht haben, der genaue code, den ich mit arbeitete. Dieser Fehler wird erzeugt, wenn die Konstante Länge eines dynamisch reservierten Arrays wird berechnet mit der run-time-Werte.
Vorausgesetzt random(a,b)
gibt ein int
zwischen a
und b
,
const int len1 = random(1,5);
char a[len1]; //Errors, since the value
//is not known at compile time (thanks to answers)
in der Erwägung, dass
const int len2 = 5;
char b[len2]; //Compiles just fine
Meine schlecht, sollte erwähnt haben, bin ich mit VC++.
Ich würde trotzdem nicht erwarten, ein Fehler.
Gut es Fehler. Ich habe den Fehler für die OP.
VC++ nimmt seinen code als auch. Fallen die
const
in der definition von len
jedoch, und es (richtig) lehnt Sie ab,; g++ wird auch ablehnen, es, falls geben Sie -std=c++98 -pedantic
als Optionen. (Es ablehnen sollten es standardmäßig, aber ich weiß nicht von jedem compiler kompiliert C++, im Gegensatz zu einigen erweiterten Sprache, in der Standardeinstellung).
InformationsquelleAutor Qix | 2012-06-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ist der Unterschied in der Lebensdauer des Arrays. Wenn Sie schreiben:
dann das array hat eine Lebensdauer des Blocks definiert (wenn es
definiert im block scope) der Klasse object enthält es (wenn es
definiert in der Klasse scope) oder statische Lebensdauer (wenn es definiert im namespace
Umfang). Wenn Sie schreiben:
dann das array hat Leben, Ihr zu geben, egal, es—Sie müssen
ausdrücklich zu kündigen, seine Lebenszeit mit:
Und mit Bezug auf Ihre Letzte Frage:
ist vollkommen legal und sollte kompilieren. Wobei es einen Unterschied gibt:
Der Grund für die Differenz ist meistens eine compiler-Technik und
Geschichte: in der sehr frühen Tagen, der compiler hatte zu wissen, die Länge in
um das array als lokale variable.
Der Grund für das fehlen von variabler Länge arrays in C++ ist nicht nur ein Zufall der compiler-tech und Geschichte. Die Größe eines Arrays ist Bestandteil der Art. I. e.
int[5]
undint[6]
sind verschiedene Arten. Ein array mit einer unbekannten Größe ist ein unvollständiger Typ ist. C++'s Weigerung zu tun, variable length arrays ist Teil der C++'s strenge Typsicherheit, und bedeutet C++ nicht machen, die situation mit rohen arrays sogar noch schlimmer als es schon ist durch die spezielle Verkleidung Dinge wie:template<class T> void foo(T &t); ... int b[random(1,5)]; foo(b); // what type is T?
Es ist dieser Aspekt auch, obwohl es ist wirklich nur relevant in C++. In der Anfangszeit von C war es definitiv ein Problem der compiler-Technologie. C99 Hinzugefügt VLAs, und wenn C++ nicht annehmen, in C++11, ist der Eingabe-Ausgabe könnte der Grund sein, oder zumindest einen Teil davon. (Ich Frage mich, was g++ tut, wenn Sie instanziieren ein array auf
int a[n]
, won
ist nicht const.)C++11 hat nicht zu eigen VLAs, und ich erwarte und hoffe, dass C++ wird es nie. g++ ermöglicht VLAs in C++ als Erweiterung, und der obige code führt zu einem Fehler:
error: no matching function for call to 'foo(int [(((unsigned int)(((int)argc) + -0x000000001)) + 1)])'
Wäre es so schwer auf das Typ-system hinzufügen VLAs, haben aber keine Zeiger-oder Referenztypen zu Ihnen? Nicht, dass ich will, VLAs, aber ich denke, man kann wahrscheinlich ersticken die special-Gehäuse in der Knospe.
InformationsquelleAutor James Kanze
Unter der Annahme einer typischen, aber etwas vereinfachte C++ - Implementierung ist, und dass der obige code wird in einer Funktion:
Den stack-pointer wird bewegt von 5 bytes, um ein 5-byte-Raum. Der name
a
bezieht sich jetzt auf block 5 bytes Speicher.Den stack-pointer wird bewegt von
sizeof(char*)
, um Platz zu schaffen fürb
. Wird eine Funktion aufgerufen, geht Weg und vergibt 5 bytes von einem Ding namens "free store", im Grunde ist es bahnt sich 5 oder mehr bytes aus einem großen block von Speicher erhalten Sie von der OS, und führt eine Buchhaltung, um sicherzustellen, dass wenn Sie kostenlos die bytes mitdelete[]
Sie werden zur Verfügung gestellt für die zukünftige Verteilung wieder zu verwenden. Es gibt die Adresse des allozierten block von 5 bytes, die gespeichert ist, in das der Speicherplatz auf dem stack fürb
.Den Grund, der zweite ist mehr Arbeit als die erste ist, dass Objekte zugewiesen mit
new
können gelöscht werden, in beliebiger Reihenfolge. Lokale Variablen (auch bekannt als "Objekte auf den stack") sind vernichtet immer in umgekehrter Reihenfolge erstellt wird, also weniger Buchführung erforderlich ist. Im Fall von trivial-zerstörbare Typen, die Umsetzung kann nur bewegen Sie den stack-pointer durch die gleiche Entfernung in die entgegengesetzte Richtung.Zu entfernen, einige der Vereinfachungen, die ich machte: der stack-pointer ist nicht wirklich bewegt, einmal für jede variable, möglicherweise ist es nur verschoben, sobald die auf Funktion Eintrag für alle Variablen in der Funktion, in diesem Fall der Platzbedarf ist mindestens
sizeof(char*) + 5
. Kann es sein, die Ausrichtung der Anforderungen auf den stack-pointer oder den einzelnen Variablen, was bedeutet, es ist nicht verschoben, von der erforderlichen Größe, sondern durch die abgerundeten-Betrag. Die Umsetzung (in der Regel der Optimierer) beseitigen können ungenutzte Variablen, oder verwenden Sie die Register für die Sie anstelle von stack-Speicher. Wahrscheinlich einige andere Dinge, die ich noch nicht gedacht.Die Sprache, die Regel ist relativ einfach: die Größe eines Arrays muss ein konstanter Ausdruck sein. Wenn ein
const int
Variablen eine Initialisierung in der gleichen TU, und die Initialisierung ist ein konstanter Ausdruck ist, dann wird die variable name kann verwendet werden, in Konstanten Ausdrücken.random(1,5)
ist nicht ein konstanter Ausdruck sein, daherlen1
kann nicht verwendet werden, die in Konstanten Ausdrücken.5
ist ein konstanter Ausdruck, solen2
ist in Ordnung.Was die Sprache, die Regel ist es, zu gewährleisten, dass die array-Größen sind zur Kompilierzeit bekannt ist. So bewegen Sie den stack, kann der compiler emittieren einer Anweisung entspricht
stack_pointer -= 5
(wostack_pointer
wirdesp
oderr13
oder was auch immer). Nach tun, dass es immer noch "weiß" genau, was offsets jede variable hat von dem neuen Wert der stack-pointer -- 5 unterscheidet sich von dem alten stack-pointer. Variable stack Zuweisungen erstellen Sie eine größere Belastung auf die Umsetzung.InformationsquelleAutor Steve Jessop
char a[5]
reserviert 5 chars auf dem stack-Speicher.new char[5]
reserviert 5 chars auf dem heap-Speicher.Beide sind erfolgreich kompiliert wurde für mich.
InformationsquelleAutor Eitan T
In C++ können Sie keine dynamischen arrays in Stapel. C99 hat diese Funktion, aber nicht in C++.
Wenn Sie erklären
char d[ len ]
Sie sind zuweisen von Speicherplatz auf stack.Wenn Sie das tun
char *c = new char[ len ]
Sie Speicherplatz auf heap.Den heap hat seinen manager und zuordnen können variable Mengen von Speicher.
In C++ muss der Stapel zugeordnet werden, indem konstanter Ausdruck Werte, so dass der compiler hat Platz für jede Menge Optimierungen.
Der compiler weiß, wie viel Platz wird für einen bestimmten Kontext auf diese Weise und ist in der Lage, vorherzusagen, stack-frames.
Mit dynamischen arrays, wäre es nicht möglich, so dass die Sprache, die Mitarbeiter beschlossen, verbieten es (zumindest bis C++11).
InformationsquelleAutor j4x
Das Dritte paar Zeilen sollte funktionieren, das sollte nicht zu einem compiler-Fehler. Es muss noch etwas anderes dort passiert.
Den Unterschied zwischen den ersten beiden Beispielen ist, dass der Speicher für
char a[5];
werden automatisch freigegeben, währendchar* b = new char[5];
reserviert Speicher auf, der nicht befreit werden, bis Sie Sie ausdrücklich frei. Ein array, das Sie zuordnen, der erste Weg, können nicht einmal verwendet werden, dass insbesondere die variable geht out of scope, da der Destruktor wird automatisch aufgerufen und der Speicher frei ist, um überschrieben werden. Für ein array erstellt mitnew
wird, kann man die Zeiger um und verwenden Sie es frei, außerhalb der ursprünglichen Variablen, und auch außerhalb der Funktion, in der es erstellt wurde, bis Siedelete
.Etwas, das Sie nicht tun können, ist:
Für die dynamische Zuweisung von Speicher, die Größe muss zur Kompilierzeit bekannt ist.
InformationsquelleAutor Daniel
Ihre einem array zugeordnet wird, die auf dem Stapel ; das bedeutet, dass, sobald das Programm kompiliert wird, es weiß, es müssen reserve 5 bytes speichert die chars mit ein. Auf der gegenüberliegenden, b ist genau erklärt, wie ein Zeiger, und deren Inhalte zugewiesen werden, die zur Laufzeit auf dem heap, und die, die fehlschlagen können, wenn der Speicher zu knapp. Schließlich, als sein wurde newed, muss es irgendwann gelöscht, oder Sie werden undicht Speicher.
InformationsquelleAutor Fabien
Wenn Sie mit neuen, Speicherzuordnung von der gratis-Speicher/heap und der Sie benötigen zu kümmern, ihn zu veröffentlichen selbst. Auch das Auffinden der freie Speicher könnte in der Tat einige Zeit in Anspruch nehmen, wie befreiend es.
Wenn Sie nicht mit neuen, Ihren Speicher wird reserviert auf dem stack und wird implizit zugewiesen und freigegeben. I. e. wenn Sie eine Funktion eingeben, wird der Aufruf-stack wird einfach zu erweitern, indem die Größe aller lokalen Variablen, die (zumindest konzeptionell - zum Beispiel, einige Variablen vorhanden sein können, vollständig in Registern) und es wird nur verringert werden, wenn Sie die Funktion verlassen.
Wenn Sie eine variable zuordnen, die mit dynamischer Größe auf dem stack wie in deinem letzten Beispiel, es bedeutet, dass Sie benötigen einige zusätzliche Informationen wenn Sie auf die Funktion scope. Insbesondere ist die Menge an Speicherplatz, der reserviert werden muss, variiert je nach Funktion-Eingänge. Nun, wenn der Kontext bestimmt werden kann, an den Anfang der Funktion, alles ist gut - das ist vermutlich, warum es erlaubt ist in C99, aber wenn Sie eine variable für die Größe, den Wert, den Sie nur wissen, mid-Funktion, die Sie bis Ende hinzufügen "fake" - Funktion aufruft. Zusammen mit C++'s-scoping-Regeln, das kann ganz schön haarig, so ist es konzeptionell viel einfacher einfach zu lassen, C++ scoping sorgen über std::vector.
InformationsquelleAutor ltjax
char a[5]
reserviert 5sizeof(char)
bytes an stack-Speicher, wennnew char[5]
reserviert diese bytes für heap-Speicher. Zugeordneten Bytes an stack-Speicher ist auch garantiert, befreit zu werden, wenn Umfang endet, im Gegensatz zu heap-Speicher, wo Sie frei werden sollte, die Speicher explizit.char d[len]
sollte erlaubt sein, da die variable deklariert ist const und damit der compiler kann leicht um den code zu reservieren diese bytes an stack-Speicher.InformationsquelleAutor weggo