Warum ist die Mehrfachdefinition einer konstanten globalen Variablen in C++ erlaubt und nicht in C?
Lesezeit: 5 Minuten
Ashwin Nanjappa
Die Mehrfachdefinition einer globalen Variablen ist in C oder C++ aufgrund der One-Definition-Rule nicht erlaubt. In C++ kann jedoch eine konstante globale Variable ohne Fehler in mehreren Kompilierungseinheiten definiert werden. Das ist nicht dasselbe wie in C.
Warum erlaubt C++ dies, während C dies nicht tut? Warum unterscheidet sich die Verwendung und das Verhalten eines konstanten Globals in C++ auf diese Weise von einem nicht konstanten Global im Vergleich zu C? Was passiert unter der Decke mit C++ und C in Bezug auf const?
Zum Beispiel ist dies in C++ erlaubt, aber in C falsch:
// Foo.cpp
const int Foo = 99;
// Main.cpp
const int Foo = 99;
int main()
{
cout << Foo << endl;
return 0;
}
Und das ist in C in Ordnung, aber in C++ falsch:
// Foo.cpp
const int Foo = 99;
// Main.cpp
extern const int Foo;
int main()
{
cout << Foo << endl;
return 0;
}
Du scheinst deine Frage selbst beantwortet zu haben…? Über welchen Teil sind Sie verwirrt?
– Merlyn Morgan-Graham
30. Mai 2011 um 8:21 Uhr
Ich vermute, er ist verwirrt darüber, dass er eine Konstante int nicht als extern deklarieren kann, ohne Verknüpfungsfehler zu erhalten.
– Iolo
30. Mai 2011 um 8:23 Uhr
Merlyn: Ich weiß, wie man const in C++ verwendet. Mich interessiert, warum const so entworfen wurde und nicht wie eine normale globale Variable?
– Ashwin Nanjappa
30. Mai 2011 um 8:24 Uhr
Dies ist wohl ein Duplikat von stackoverflow.com/questions/998425/…
– MSalter
30. Mai 2011 um 8:58 Uhr
Nawaz
// Foo.cpp
const int Foo = 99;
// Main.cpp
const int Foo = 99;
const Variable im Namespace-Bereich hat intern Verknüpfung. Sie sind also im Grunde zwei verschiedene Variablen. Es gibt keine Neudefinition.
Aus @ Davids Kommentar, 3,5/3 [basic.link]:
Ein Name mit Namensraumbereich (3.3.5) hat interne Verknüpfung wenn es der Name ist
— ein Objekt, eine Referenz, eine Funktion oder eine Funktionsvorlage, die explizit als statisch deklariert ist, oder
— ein Objekt oder eine Referenz, das ist ausdrücklich als const deklariert und weder explizit als extern deklariert noch zuvor als externe Verknüpfung deklariert; oder
— ein Datenmitglied einer anonymen Vereinigung.
Im zweiten Fall sollten Sie dies tun (richtiger Weg):
//Foo.h
extern const int Foo; //use extern here to make it have external linkage!
// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here
// Main.cpp
#include "Foo.h"
int main()
{
cout << Foo << endl;
}
Danke Nawaz. Wird dies irgendwo im Buch zur Programmiersprache C++ oder in einer anderen Referenz erklärt?
– Ashwin Nanjappa
30. Mai 2011 um 8:22 Uhr
Im Standard… 3,5/3 [basic.link]: Ein Name mit Namespace-Geltungsbereich (3.3.5) hat eine interne Verknüpfung, wenn es sich um den Namen handelt von – einem Objekt, einer Referenz, einer Funktion oder einer Funktionsvorlage, die ausdrücklich als statisch deklariert ist, oder – ein Objekt oder eine Referenz, die explizit als const deklariert und weder explizit als extern deklariert noch zuvor als externe Verknüpfung deklariert wurde; oder — ein Datenmitglied einer anonymen Vereinigung.
– David Rodríguez – Dribeas
30. Mai 2011 um 8:26 Uhr
@David: Ich habe deinen Kommentar in meinem Beitrag zitiert. Ich habe nach der Anfrage von @Ashwin im Standard nach diesem Text gesucht, aber Sie haben mir die Arbeit leicht gemacht. Hoffe es stört dich nicht.
– Nawaz
30. Mai 2011 um 8:30 Uhr
Ich denke, sollte enthalten Foo.h in Foo.cpp auch sonst Foo ist nicht mit externer Verlinkung deklariert.
– Matthias M.
30. Mai 2011 um 8:46 Uhr
@Matthieu: Stimmt. Ich habe nur vergessen, das zu tun. Vielen Dank 🙂
– Nawaz
30. Mai 2011 um 8:49 Uhr
Ich denke, Sie fragen nach der Begründung und nicht nach der spezifischen Sprachregel, die dies zulässt.
Die Begründung dafür ist, dass es macht const Variablen viel einfacher zu verwenden. Es gibt einen typisierten Ersatz für eine häufige Verwendung von #define.
Anstatt von #define MAX_COUNT 211 Sie können verwenden const int max_count = 211; auf genau die gleiche Weise, zB eine gemeinsam genutzte Header-Datei, ohne sich Gedanken darüber machen zu müssen, wo die eine Definition abgelegt werden soll.
Sie können den Wert von a nicht legal ändern const Objekt, sodass es keinen sichtbaren Unterschied zwischen einem Objekt und mehreren Objekten mit demselben Wert gibt.
Wie Sie eine Definition von a setzen können const -Objekt in einer Header-Datei macht es für den Compiler trivial, den Wert direkt in der Kompilierungsphase zu verwenden, ohne dass solche Optimierungen auf eine Korrektur zur Verbindungszeit verzögert werden müssen.
Können Sie auch erklären, warum sich dieses C++-Verhalten von const von C unterscheidet? Der obige Code, der in C++ funktioniert, hat einen Mehrfachdefinitionsfehler in C!
– Ashwin Nanjappa
30. Mai 2011 um 8:40 Uhr
@Ashwin: Ich fürchte nicht. Ich glaube, dass C mehr Abwärtskompatibilitätsprobleme hatte (unterstützende vorläufige Definitionen?) und am Ende eine kompromittiertere Version hatte const aber ich habe keine direkten Beweise dafür.
– CB Bailey
30. Mai 2011 um 8:43 Uhr
@AshwinNanjappa Ich nehme an, C zieht es in diesem Fall einfach vor, die Verwendung von Schlüsselwörtern konsistent zu halten – wenn Sie static angeben, erhalten Sie eine interne Verknüpfung. Andernfalls erhalten Sie eine externe Verlinkung 🙂
– Martinkunew
16. November 2015 um 14:13 Uhr
Grundsätzlich sind in C++ const, nicht lokale Variablen echte konstante Ausdrücke oder constexpr. Dies erlaubt viele Dinge, wie TMP.
const int five = 5;
int main() {
int x[five];
std::array<int, five> arr;
}
In C sind sie nur eine Variable, die nicht geändert werden kann. Das ist,
const int five = 5;
int main() {
int x[five]; // Technically, this is a variable length array
}
Ist durchaus gleichwertig
int five = 5;
int main() {
int x[five];
}
Tatsächlich fördert C++ einige Arten von const Variable in eine neue Kategorie, constexprwährend dies in C nicht existiert und es sich nur um Variablen handelt, die zufällig nicht änderbar sind.
Alex B
Es sieht aus wie konst erzeugt nicht wirklich ein externes Symbol.
Warum schreiben Engländer COLOUR, während Amerikaner es COLOR buchstabieren?
Es sind 2 verschiedene Sprachen von der gleichen Basis, aber sie haben nicht die gleichen Regeln.
C und C++ sind gleich. Wenn sie nicht verschieden wären, würden sie beide gleich heißen.
“Warum sind sie anders?” “Weil sie nicht gleich sind!” Nicht nützlich.
– josaphatv
20. Mai 2015 um 20:59 Uhr
hkf
Meine Problemumgehung deklarierte es als:
static classfoo foo;
es hat in meiner Situation funktioniert.
“Warum sind sie anders?” “Weil sie nicht gleich sind!” Nicht nützlich.
– josaphatv
20. Mai 2015 um 20:59 Uhr
13678500cookie-checkWarum ist die Mehrfachdefinition einer konstanten globalen Variablen in C++ erlaubt und nicht in C?yes
Du scheinst deine Frage selbst beantwortet zu haben…? Über welchen Teil sind Sie verwirrt?
– Merlyn Morgan-Graham
30. Mai 2011 um 8:21 Uhr
Ich vermute, er ist verwirrt darüber, dass er eine Konstante int nicht als extern deklarieren kann, ohne Verknüpfungsfehler zu erhalten.
– Iolo
30. Mai 2011 um 8:23 Uhr
Merlyn: Ich weiß, wie man const in C++ verwendet. Mich interessiert, warum const so entworfen wurde und nicht wie eine normale globale Variable?
– Ashwin Nanjappa
30. Mai 2011 um 8:24 Uhr
Dies ist wohl ein Duplikat von stackoverflow.com/questions/998425/…
– MSalter
30. Mai 2011 um 8:58 Uhr