Почему множественное определение глобальной переменной const разрешено в С++, а не в C?
Множественное определение глобальной переменной не допускается на C или С++ из-за правила One Definition. Однако в С++ глобальная переменная const может быть определена в нескольких единицах компиляции без ошибок. Это не то же самое, что в C.
Почему С++ разрешает это, пока C не работает? Почему использование и поведение глобального константа отличаются от неконстантного глобального таким образом в С++ по сравнению с C? Что происходит под обложками с С++ и C относительно const?
Например, это разрешено в С++, но неправильно в C:
// Foo.cpp
const int Foo = 99;
// Main.cpp
const int Foo = 99;
int main()
{
cout << Foo << endl;
return 0;
}
И это хорошо с C, но неправильно с С++:
// Foo.cpp
const int Foo = 99;
// Main.cpp
extern const int Foo;
int main()
{
cout << Foo << endl;
return 0;
}
Ответы
Ответ 1
// Foo.cpp
const int Foo = 99;
// Main.cpp
const int Foo = 99;
const
переменная в пространстве имен имеет внутреннюю связь. Таким образом, они в основном две разные переменные. Нет переопределения.
Из комментария @David, 3.5/3 [basic.link]:
Имя, имеющее область пространства имен (3.3.5) имеет внутреннюю связь, если это имя из
- объект, ссылка, функция или функциональный шаблон, который явно объявлено статическим или,
- объект или ссылка явно объявлена const и не объявлено явно извне или ранее объявлен внешняя связь; или
- член данных анонимного союза.
Во втором случае вы должны делать это (правильный путь):
//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;
}
Ответ 2
Я думаю, что вы просите об обосновании, а не о конкретном правиле языка, которое позволяет это.
Обоснование этого состоит в том, что он облегчает использование переменных const
. Он дает типизированную замену для одного общего использования #define
.
Вместо #define MAX_COUNT 211
вы можете использовать const int max_count = 211;
точно так же, например. общий заголовочный файл, не беспокоясь о том, где поставить одно определение.
Вы не можете юридически изменить значение объекта const
, чтобы не было видимой разницы между наличием одного объекта и нескольких объектов с тем же значением.
Как вы можете поместить определение объекта const
в заголовочный файл, для компилятора тривиально использовать значение непосредственно на этапе компиляции, при этом такие оптимизации не должны быть отложены до фиксации времени ссылки.
Ответ 3
В основном, в С++ константные, нелокальные переменные являются подлинными константными выражениями или constexpr. Это позволяет много вещей, таких как TMP.
const int five = 5;
int main() {
int x[five];
std::array<int, five> arr;
}
В C это просто переменная, которая не может быть изменена. То есть
const int five = 5;
int main() {
int x[five]; // Technically, this is a variable length array
}
Достаточно эквивалентно
int five = 5;
int main() {
int x[five];
}
Фактически, С++ продвигает некоторые виды переменной const
в новую категорию, constexpr
, тогда как в C это не существует, и они являются просто переменными, которые не подлежат модификации.
Ответ 4
Похоже, что const фактически не генерирует внешний символ.
Ответ 5
Почему английские люди заклинают ЦВЕТ, тогда как американские люди заклинают его ЦВЕТ?
Это два разных языка из одной базы, но они не имеют одинаковых правил.
C и С++ - то же самое. Если бы они не были разными, их оба называли бы одним и тем же.
Ответ 6
Мое обходное объявление объявляло это как:
static classfoo foo;
он работал в моей ситуации.