Eine Frage zu const in Bezug auf static
-
Effective C++ Second Edition, Item 21, Paragraph 2 schrieb:
The const keyword is remarkably versatile. Outside of classes, you can use it for global or namespace constants (see Item 1 and 47) and for static objects (local to a file or a block). Inside classes, you can use it for both static and nonstatic data members (see also Item 12).
Er hat also non-static Objekte innerhalb von Funktionen/Blöcken vergessen.
void foo() { int const meyersForgotMe = foo(); { int const andMeToo = bar(); } }Macht nix, das Buch ist trotzdem gut

-
Ok, also wie ich dachte, er hat quasi vergessen das ganze auf nicht-statische Objekte zu beziehen. Ich kann es ja auch für statische Objekte im globalen Gültigkeitsbereich oder Gültigkeitsbereich von Namensbereichen nutzen.
Es hätte also zum Beispiel so heißen müssen:
Das Schlüsselwort const ist bemerkenswert vielfältig. Außerhalb von Klassen können Sie es für Beschränkungen im globalen Gültigkeitsbereich oder dem Gültigkeitsbereich von Namensbereichen verwenden sowie für Objekte, die im Gültigkeitsbereich einer Datei, einer Fuktion oder eines Blocks deklariert sind, oder in diesen genannten Bereichen als static deklariert sind. .....
Oder?
Danke schonmal, Fragensteller123
-
Hmja.
Ich denke es hätte ein "überall wo man nen Typ angibt, kann man const dazuschreiben" gereicht. Zumindest fällt mir gard nix ein wo es nicht ginge.

-
Fragensteller123 schrieb:
Ok, also wie ich dachte, er hat quasi vergessen das ganze auf nicht-statische Objekte zu beziehen. Ich kann es ja auch für statische Objekte im globalen Gültigkeitsbereich oder Gültigkeitsbereich von Namensbereichen nutzen.
Es hätte also zum Beispiel so heißen müssen:
Das Schlüsselwort const ist bemerkenswert vielfältig. Außerhalb von Klassen können Sie es für Beschränkungen im globalen Gültigkeitsbereich oder dem Gültigkeitsbereich von Namensbereichen verwenden sowie für Objekte, die im Gültigkeitsbereich einer Datei, einer Fuktion oder eines Blocks deklariert sind, oder in diesen genannten Bereichen als static deklariert sind. .....
Oder?
Danke schonmal, Fragensteller123
Aber const static im globalen Gültigkeitsbereich ist ja eigentlich unnötig, denn durch const, wird die Variable ja schon auf die eine Übersetzungseinheit beschränkt.
Lg freeG
-
fr33g schrieb:
Aber const static im globalen Gültigkeitsbereich ist ja eigentlich unnötig, denn durch const, wird die Variable ja schon auf die eine Übersetzungseinheit beschränkt.
Hä? Nein!
-
LordJaxom schrieb:
fr33g schrieb:
Aber const static im globalen Gültigkeitsbereich ist ja eigentlich unnötig, denn durch const, wird die Variable ja schon auf die eine Übersetzungseinheit beschränkt.
Hä? Nein!
Doch, im Prinzip schon.
C++03-Standard, §7.1.5.1, Satz 2 schrieb:
An object declared in namespace scope with a const-qualified type has internal linkage unless it is explicitly declared
externor unles it was previously declared to have external linkage. [...]
-
Ist laut dem neuen Standard eigentlich noch folgendes erlaubt
static int global = 5; int main() { }denn eigentlich sollte man ja nur noch
namespace { int global = 5; } int main() { }nutzen oder nicht?
Gilt es eg nur für den unbenannten Namensbereich, dass die Elemente nur in der einen Übersetzungseinheit sichtbar sind, oder gilt das auch für benannte Namensbereiche?
Lg freeG
-
fr33g schrieb:
Ist laut dem neuen Standard eigentlich noch folgendes erlaubt
static int global = 5; int main() { }Ist erlaubt (N3291). Es werden auch explizit Beispiele genannt, z.B. Example zu §7.1.1,8 (static int a im global namesace scope.
fr33g schrieb:
Gilt es eg nur für den unbenannten Namensbereich, dass die Elemente nur in der einen Übersetzungseinheit sichtbar sind, oder gilt das auch für benannte Namensbereiche?
Das nennt sich internal linkage, und gilt für diverse Dinge:
- alles was static deklariert wurde im namespace scope (inclusive global namespace scope)
- alle Variablen die explizitconstoderconstexprdeklariert wurden im namespace scope (inclusive global namespace scope), wenns nicht vorher mit externer linkage deklariert wurde
- daten-member von anonymen unions im namespace scope (inclusive global namespace scope)
- anonyme namespaces und alle namespaces darin
- alles was an variablen, Klassen, Funktionen in namespaces mit internal linkage deklariert wird.
Bsp:namespace { namespace named_in_unnamed { void foo(); //internal linkage obowohl nicht direkt im unnamed namespace } }Es gibt noch einige komplizierte Details, die auch interne linkage haben, aber das liest du am besten in N3291 selber nach

-
Hey vielen Dank für die ausführliche Antwort=)
Also habe ich es richtig verstanden, dass es auch für bennante Namespaces gilt!?
Du redest hier ja die ganze Zeit von Deklarationen, wenn ich was im Namespace definiere, gilt ja aber das gleiche oder? Denn eine Definition beinhaltet ja eine Deklaration.Lg freeG und schonmal vielen lieben Dank
-
fr33g schrieb:
Also habe ich es richtig verstanden, dass es auch für bennante Namespaces gilt!?
Nur für benannte Namespaces mit interner linkage! Benannte Namespaces haben interne linkage, wenn sie in einem unbenannten Namespace liegen, oder in einem anderen benannten Namespace mit interner linkage.
Im Klartext heißt das:
- unbenannte Namespaces haben interne linkage
- benannte Namespaces haben interne linkage, wenn sie direkt oder indirekt in einem unbenannten Namespace liegen.Du redest hier ja die ganze Zeit von Deklarationen, wenn ich was im Namespace definiere, gilt ja aber das gleiche oder? Denn eine Definition beinhaltet ja eine Deklaration.
Jein. Du kannst etwas deklarieren und danach irgendwann definieren - es gilt, was bei der ersten Deklaration angegeben wurde. Beispiel:
static void foo(); //Deklaration, interne linkage dank static /* ... */ void foo() //Definition, keine Deklaration, interne linkage dank der Dekaration oben. { /* ... */ }
-
Ok, dass ist mir jetzt klar.
Aber eine Frage ist mir gerade noch aufgetaucht: Wenn ich was in einem Namespace deklariere bzw definiere, dann ist es doch statisch oder? Also statisch bedeutet ja, es wird bei der Definition erstellt und existiert bis zum Programmende.Lg freeG
-
fr33g schrieb:
Ok, dass ist mir jetzt klar.
Aber eine Frage ist mir gerade noch aufgetaucht: Wenn ich was in einem Namespace deklariere bzw definiere, dann ist es doch statisch oder? Also statisch bedeutet ja, es wird bei der Definition erstellt und existiert bis zum Programmende.Nein, statisch im sinne von "static" ist was anderes. Da gibts die Unterschiede
- static in namespace scope (erzeug interne linkage)
- static im Klassen-Scope (nur einmal pro Klasse vorhanden)
- static im Funktions-Scope (wird beim ersten Aufruf der Funktion initialisiert und besteht bis Programmende)Wenn du etwas in einem Namespace deklariest/definierst, hängts davon ab, was du da definierst:
- Variablen im namespace scope existieren von Programmstart bis Programmende
- Funktionen werden eh vom Compiler übersetzt, die existieren nicht mehr in dem Sinne, dass sie Speicher auf dem Stack oder Heap verbrauchen. Wenn sie vom Compiler inlined werden, existieren eh nurnoch die Namen zur Compilezeit, danach garnichts mehr, nurnoch Codestückchen als Teile von anderem übersetztem Code.
- Klassen im namespace scope exisiteren an sich nur als Namen zur Compielzeit. Zur Laufzeit bleibt höchstens noch eine vtable und RTTI übrig und evtl. irgendwo ein bisschen Platz für die statischen Membervariablen. (Im Unterschied zu den Objekten der Klasse, die zur Laufzeit Erzeugt und vernichtet werden)
- enums existieren wie Klassen nur als Namen (Im UNterschied zu Variablen des enum-Typs)
- templates existieren nur bis zu ihrer Instantiierung, d.h. auch nur zur Compilezeit, danach sind die inatntiierten Templates nicht viel mehr als banale Klassen, die aber auch nurnoch zur Compilezeit existieren (s.o.)Du siehst, es gibt viele Dinge, die man in namespaces definieren und deklarieren kann, und nicht alle "existieren" jemals so richtig, geschweige denn zur Laufzeit

Zu deinem Ausdruck "Bei der Definition erstellt" von Variablen (ich denk mal darum gehts dir hauptsächlich): Die Definition ist eine Compilezeit-Angelegenheit. Die "Erstellung" der Variable ist eine zweiteilige Angelegenheit: Reservierung des Speichers und Initialisierung des Speicherbereichs. Beides geschieht zu "Programmstart" und endet am "Programmende".
Dabei ist Programmstart und Programmende eine etwas schwammige Sache: Die Variablen werden irgendwann vor Betreten der main initialisiert. Das kann aber durchaus ne ganze Weile dauern und vor der Initialisierung einer Variable können zig andere Dinge passieren (Funktionen aufgerufen werden usw). Beispiel:
#include <iostream> #include <cstdlib> int foo() { std::cout << "Hallo Welt! \n"; return EXIT_SUCCESS; } int bar() {std::cout << "i2 ist dran!\n"; return EXIT_FAILURE;} const int i = foo(); const int i2 = bar(); int main() { if (i != 0) return i2; return i; }hier passiert alles "wichtige" in der Methode foo, und zwar vor der Initialisierung von i2 (und vor der main sowieso)
-
Vielen Dank pumuckl, jetzt ist es mir klar=)
Lg freeG