Объявление массива, размер которого объявляется как extern const

У меня есть проблема с инициализацией массива, размер которого определяется как extern const. Я всегда следовал правилу о том, что глобальные переменные должны быть объявлены как extern в файлах заголовков, и их соответствующие определения должны быть в одном из файлов реализации, чтобы избежать ошибок перерисовки переменных. Этот подход работал нормально, пока мне не пришлось инициализировать массив, размер которого определяется как extern const. Я получаю сообщение об ошибке, что ожидается постоянное выражение. Однако, если я попытаюсь присвоить значение переменной const, компилятор правильно сообщит, что значение не может быть присвоено постоянной переменной. Это фактически доказывает, что компилятор видит переменную как константу. Почему тогда возникает ошибка, когда я пытаюсь объявить массив того же размера?

Есть ли способ избежать этого, не используя #define? Я также хотел бы узнать причину этой ошибки.

Package.h:

#ifndef PACKAGE_H
#define PACKAGE_H

extern const int SIZE;

#endif

Package.cpp:

#include "Package.h"

const int SIZE = 10;

foo.cpp:

#include "Package.h"

int main()
{
    // SIZE = 5; // error - cannot assign value to a constant variable
    // int Array[SIZE]; // error - constant expression expected
    return 0;
}

Ответ 1

Константа является внешней, поэтому она определена в другом модуле компиляции (.o file). Поэтому компилятор не может определить размер вашего массива во время компиляции; неизвестно до тех пор, пока не свяжет время, какое будет значение константы.

Ответ 2

Ну, он видит переменную как const, а не как константное выражение.

Ответ 3

Так как это просто int, я бы удалил extern и сделал бы это определение, а не декларацию. Причина, по которой я говорю, заключается в том, что, хотя этот подход помещает отдельный экземпляр целого в каждый исходный файл, который включает заголовок, я бы предположил, что большинство компиляторов оптимизирует его использование. На самом деле компилятор не может оптимизировать его использование, если вы этого не сделаете, поэтому он не будет оптимизирован из простых арифметических выражений.

Поскольку он объявлен const, он будет иметь внутреннюю связь, и поэтому вы не будете получать многократно заданные проблемы с символами, сделав это таким образом.

Ответ 4

Я считаю, что проблема заключается в том, что если вы объявляете свою переменную как extern, ей разрешается находиться в другом модуле (файл .o) или даже в динамической библиотеке (.dll/.so). Это, конечно, означает, что компилятор, возможно, не сможет разрешить содержимое переменной во время компиляции, тем самым отказываясь использовать значение, в котором требуется константа.

Мое мнение заключается в том, что совершенно нормально не использовать extern здесь и объявлять его непосредственно в файле заголовка, так как это значение int в любом случае будет включено в случае использования в любом месте кода. Обычно я использую extern const только при работе со строками, так как я хочу убедиться, что во время выполнения генерируется только один экземпляр строки.