Zitat von
Matze:
Mir stellen sich nun einige Fragen und zwar diese:
Code:
const int i = 5; // "sizeof i" liefert 4 Bytes
// mir wurde jedoch gesagt, Konstanten belegen keinen Speicher, was nun?
Konstanten belegen durchaus Speicher. Sie müssen im Speicher existieren und eine Adresse haben, da man sie z.B. an Funktionen wie
Code:
void foo (const int& bar);
übergeben kann.
Wenn aber der Compiler feststellt, daß die Konstante nicht referenziert wird, kann er sie wegoptimieren (was in der Praxis meistens geschieht).
Zitat von
Matze:
Code:
enum {A, B, C, D}; // "sizeof A" liefert 4 Bytes, ist im Prinzip aber auch eine Konstante
Das gleiche gilt hier.
Zitat von
Matze:
Code:
struct komplex { // Ich hätte auf eine Dekl. getippt, aber "sizeof komplex" liefert 8 Bytes, wieso? o.O
double Realteil;
double Imaginaerteil;
};
In der Tat seltsam - eigentlich sollten es 16 Bytes sein
komplex ist eine Struktur, und mit sizeof(komplex) erfährst du, wieviel Bytes eine Instanz dieser Struktur benötigt. sizeof(instanz_von_komplex) liefert das gleiche Ergebnis.
Zur allgemeinen Vermeidung der Verwechslung von Deklaration und Definition mag es sinnvoll sein, "Implementation" statt "Definition" zu benutzen.
Ansonsten gilt:
- eine Deklaration "deklariert" ein Objekt oder eine Funktion, macht es bekannt.
- eine Definition "beschreibt" bzw. "implementiert" ein Objekt oder eine Funktion.
Aus Sicht des Compilers:
- eine Deklaration gibt die Information an, die der Compiler für den Umgang mit dem Objekt oder der Funktion benötigt (für Objekte: Datentyp, Größe, Methoden; für Funktionen: Rückgabetyp, Parameterzahl, Parametertypen).
- eine Vorwärtsdeklaration eines Typs macht nur seinen Namen verfügbar. Da seine Größe nicht bekannt ist, kann er nicht instantiiert werden; es können lediglich Zeiger und Referenzen auf ihn benutzt werden.
- eine Definition implementiert die durch die Deklaration beschriebene Funktionalität. Sie ist für den Compiler für Aufrufe der Funktion oder Instantiierungen des Typs nicht vonnöten, erst der Linker führt Implementation und Referenzen zusammen. (Ausnahme sind hier Templates; da hier die Typinformation bei der Deklaration nicht vollständig ist (man kann jeden beliebigen Typ als Templateparameter einsetzen, auch Typen, die erst später deklariert werden), ist es nicht möglich, eine spezialisierte Implementation bereitzustellen; die generische Implementation muß dem Compiler folglich zur Verfügung stehen, da er sie zur Spezialisierung benötigt.)
Code:
extern int i; // Deklaration
int i; // Definition
extern void foo (void); // Deklaration; extern ist hier optional und wird per Default angenommen
void foo (void) {} // Definition bzw. Implementation
class myClass; // Vorwärtsdeklaration
class myClass // Deklaration
{
public:
void bar (void);
};
void myClass::bar (void) // Definition bzw. Implementation
{
foo ();
}