Die Unterschiede zwischen Initialisieren, Definieren und Deklarieren einer Variablen


79

Nachdem ich die Frage gelesen habe , kenne ich die Unterschiede zwischen Deklaration und Definition. Bedeutet das also, dass Definition gleich Deklaration plus Initialisierung ist?


1
Die Initialisierung erfolgt für Variablen. Die Definition kann auch für Funktionen gelten, bei denen Sie den Körper definieren.
FKaria

Meinst du also für eine Variable, es ist richtig.
Tony

Antworten:


98

Erklärung

Die Erklärung bezieht sich im Allgemeinen auf die Einführung eines neuen Namens in das Programm. Sie können beispielsweise eine neue Funktion deklarieren, indem Sie ihre "Signatur" beschreiben:

void xyz();

oder einen unvollständigen Typ deklarieren:

class klass;
struct ztruct;

und zu guter Letzt, um ein Objekt zu deklarieren:

int x;

Es wird im C ++ - Standard in §3.1 / 1 beschrieben als:

Eine Erklärung (Abschnitt 7) kann einen oder mehrere Namen in eine Übersetzungseinheit einführen oder Namen, die durch frühere Erklärungen eingeführt wurden, neu deklarieren.

Definition

Eine Definition ist eine Definition eines zuvor deklarierten Namens (oder kann sowohl Definition als auch Deklaration sein). Zum Beispiel:

int x;
void xyz() {...}
class klass {...};
struct ztruct {...};
enum { x, y, z };

Insbesondere definiert es der C ++ - Standard in §3.1 / 1 als:

Eine Deklaration ist eine Definition, es sei denn, sie deklariert eine Funktion ohne Angabe des Funktionskörpers (8.4), enthält den externen Bezeichner (7.1.1) oder eine Verknüpfungsspezifikation25 (7.5) und deklariert weder einen Initialisierer noch einen Funktionskörper statisches Datenelement in einer Klassendefinition (9.2, 9.4), es ist eine Klassennamendeklaration (9.1), es ist eine Opaque-Enum-Deklaration (7.2), es ist ein Template-Parameter (14.1), es ist ein Parameter- Deklaration (8.3.5) in einem Funktionsdeklarator, der nicht der Deklarator einer Funktionsdefinition ist, oder es ist eine typedef-Deklaration (7.1.3), eine Alias-Deklaration (7.1.3), eine using-Deklaration (7.3). 3), eine static_assert-Deklaration (Klausel 7), eine Attributdeklaration (Klausel 7), eine leere Deklaration (Klausel 7) oder eine using-Direktive (7.3.4).

Initialisierung

Die Initialisierung bezieht sich auf die "Zuweisung" eines Werts zur Konstruktionszeit. Für ein generisches Objekt vom Typ That es häufig die folgende Form:

T x = i;

aber in C ++ kann es sein:

T x(i);

oder auch:

T x {i};

mit C ++ 11.

Fazit

Bedeutet das also, dass Definition gleich Deklaration plus Initialisierung ist?

Es hängt davon ab, ob. Worüber sprichst du? Wenn Sie über ein Objekt sprechen, zum Beispiel:

int x;

Dies ist eine Definition ohne Initialisierung. Das Folgende ist stattdessen eine Definition mit Initialisierung:

int x = 0;

In bestimmten Zusammenhängen ist es nicht sinnvoll, von "Initialisierung", "Definition" und "Deklaration" zu sprechen. Wenn Sie beispielsweise über eine Funktion sprechen, bedeutet die Initialisierung nicht viel.

Die Antwort lautet also nein : Definition bedeutet nicht automatisch Deklaration plus Initialisierung.


12
Nicht ganz: int x;ist sowohl eine Definition als auch eine Erklärung.
Angew ist nicht mehr stolz auf SO

2
@Angew, danke, ich habe eine vollständigere Definition hinzugefügt .
Schuh

Ich denke, die Frage, die OP in seinem Beitrag erwähnt hat, beantwortet Definition und Erklärung ziemlich gut. Aber die ursprüngliche Frage war So does it mean definition equals declaration plus initialization.
Tahlil

@ Tahlil, fügte eine Schlussfolgerung hinzu. Danke, dass du mich darauf aufmerksam gemacht hast.
Schuh

3
@ Tony Ich denke (bitte jemand korrigiert mich, wenn ich falsch liege, damit ich lerne) 'extern int x' macht es nur zu einer Deklaration, was bedeutet, dass die Definition an anderer Stelle gefunden wird. Während 'int x' es tatsächlich definiert, obwohl es mit einem zufälligen Müllwert versehen wird, es sei denn, Sie initialisieren es speziell wie 'int x = 5'.
Göre

39

In der Erklärung heißt es: "Dieses Ding existiert irgendwo":

int foo();       // function
extern int bar;  // variable
struct T
{
   static int baz;  // static member variable
};

Definition sagt "dieses Ding existiert hier; machen Sie Erinnerung daran":

int foo() {}     // function
int bar;         // variable
int T::baz;      // static member variable

Die Initialisierung ist zum Zeitpunkt der Definition für Objekte optional und lautet "Hier ist der Anfangswert für dieses Objekt":

int bar = 0;     // variable
int T::baz = 42; // static member variable

Manchmal ist es stattdessen zum Zeitpunkt der Deklaration möglich:

struct T
{
   static int baz = 42;
};

… Aber das führt zu komplexeren Funktionen.


Sehr gut erklärt, außer dass die Initialisierung etwas komplexer ist. (Dies wäre nicht C ++, wenn es so einfach wäre.) Die Initialisierung umfasst Dinge wie die Nullinitialisierung von Variablen mit statischer Lebensdauer und Standardkonstruktoren sowie das, was Sie anzeigen. (Und um die Verwirrung zu vergrößern: In C kann die Initialisierung das erste Mal sein, dass die Variable zugewiesen wird, z. B. in Anweisungen wie "den Wert einer nicht initialisierten Variablen annehmen". Es würde mich nicht wundern, wenn ein Teil davon auch in die Variable gerutscht wäre C ++.)
James Kanze

Oh, und es gibt auch Sonderfälle, in denen C ++ die Angabe der Initialisierung in einer Deklaration zulässt.
James Kanze

1
@ JamesKanze: Beschlossen, es für diese Zwecke super einfach zu halten
Leichtigkeitsrennen im Orbit

6

Zumindest für C gemäß C11 6.7.5:

Eine Deklaration gibt die Interpretation und Attribute einer Reihe von Bezeichnern an. Eine Definition eines Bezeichners ist eine Deklaration für diesen Bezeichner, die:

  • bewirkt für ein Objekt, dass der Speicher für dieses Objekt reserviert wird;

  • schließt für eine Funktion den Funktionskörper ein;

  • für eine Aufzählungskonstante ist die (einzige) Deklaration des Bezeichners;

  • ist für einen typedef-Namen die erste (oder einzige) Deklaration des Bezeichners.

Gemäß C11 6.7.9.8-10:

Ein Initialisierer gibt den in einem Objekt gespeicherten Anfangswert an. Wenn ein Objekt mit automatischer Speicherung nicht explizit initialisiert wird, ist sein Wert unbestimmt.

Im Großen und Ganzen führt eine Erklärung eine Kennung ein und liefert Informationen darüber. Für eine Variable ist eine Definition eine Deklaration, die Speicher für diese Variable zuweist.

Die Initialisierung ist die Angabe des Anfangswertes, der in einem Objekt gespeichert werden soll. Dies ist nicht unbedingt derselbe wie beim ersten expliziten Zuweisen eines Werts. Eine Variable hat einen Wert, wenn Sie sie definieren, unabhängig davon, ob Sie ihr explizit einen Wert geben oder nicht. Wenn Sie ihm keinen expliziten Wert geben und die Variable automatisch gespeichert wird, hat sie einen Anfangswert, aber dieser Wert ist unbestimmt. Wenn es statischen Speicher hat, wird es abhängig vom Typ implizit initialisiert (z. B. werden Zeigertypen auf Nullzeiger initialisiert, arithmetische Typen werden auf Null initialisiert usw.).

Wenn Sie also eine automatische Variable definieren, ohne einen Anfangswert dafür anzugeben, z.

int myfunc(void) {
    int myvar;
    ...

Sie definieren es (und deklarieren es daher auch, da Definitionen Deklarationen sind), initialisieren es jedoch nicht. Daher ist Definition nicht gleich Deklaration plus Initialisierung.


In C ++ unterscheidet sich die Initialisierung erheblich. (C hat auch das Äquivalent der Nullinitialisierung von Objekten mit statischer Lebensdauer.)
James Kanze

@JamesKanze: Ja, leider ist diese Frage sowohl mit C als auch mit C ++ gekennzeichnet, was in den Punkten, in denen sie sich unterscheiden, nicht sehr hilfreich ist.
Crowman

Ziemlich. Für die kompatiblen Typen bestand die Absicht (zumindest ursprünglich) in C ++ darin, dass sie sich wie in C verhalten. Tatsächlich denke ich, dass sie sich in allen Fällen, in denen die Sprachen selbst kompatibel sind, immer noch gleich verhalten. Der zur Definition dieses Verhaltens verwendete Wortlaut ist jedoch ganz anders.
James Kanze

1

"Das bedeutet also, dass Definition gleich Deklaration plus Initialisierung ist."

Es ist nicht unbedingt erforderlich, dass Ihre Deklaration ohne Initialisierung einer Variablen wie folgt lautet:

 void helloWorld(); //declaration or Prototype.

 void helloWorld()
 {
    std::cout << "Hello World\n";
 } 
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.