Статические глобальные переменные в С++
Я хотел бы сделать массив целых чисел через метод malloc. Я хочу, чтобы этот массив был глобальным и использовался в моей программе. Я помещаю код в заголовочный файл, который выглядит так:
static int *pieces;
Тогда у меня есть функция, которая заполняет ее числами, которые я хочу там. Функция находится в пространстве имен, а пространство имен реализовано в собственном .cpp файле. Тем не менее, я импортирую файл заголовка в main.c и вызываю функцию из пространства имен, которое создает такой массив, как:
pieces = malloc(sizeof(int) * 128);
Но когда я пытаюсь получить доступ к номерам в главном массиве (после вызова функции, которая создает мой массив), он сбой и говорит, что части не были инициализированы. Но в функции я могу ее создать и манипулировать цифрами в ней просто отлично. У меня создалось впечатление, что, ставя куски статической переменной, всякий раз, когда какая-либо функция меняет (или устанавливает ее), это повлияет на использование переменной где угодно. В основном, что я пытаюсь сказать, почему части кажутся неуправляемыми в основном, хотя я установил его в функции, которую я назвал?
Ответы
Ответ 1
Static
- это ключевое слово со многими значениями, и в этом конкретном случае это означает не глобальный (перефразирование)
Это означает, что каждый .cpp
файл имеет свою собственную копию. Таким образом, при инициализации в main.cpp
, он инициализируется ТОЛЬКО в main.cpp
. Другие файлы все еще не инициализированы.
Прежде всего, чтобы исправить это, нужно удалить ключевое слово Static
. Это приведет к возникновению проблемы "Несколько определений". Чтобы исправить это, вы должны определить переменную в файле .cpp
и просто extern объявить ее в файле заголовка.
Изменить: вы просто выделяете ему память, не считается инициализацией. Вам необходимо инициализировать память до 0 после выделения.
Вы можете использовать new int[128]()
вместо вашего более подробного синтаксиса malloc
, и это будет выполнить инициализацию? Или вы можете взять легкий путь (для чего он нужен) и использовать std::vector
Ответ 2
Ключ таков:
static int *pieces;
Ты сказал, что положил это в свой заголовок. Это не способ экспорта символа. Любой файл, который включает заголовок, получит свою собственную статическую версию неинициализированного указателя под названием pieces
.
Вместо этого вы помещаете это в свой заголовок:
extern int *pieces;
extern int init_pieces();
И в исходном файле вы выполните следующее:
static const size_t num_pieces = 128;
int *pieces = 0;
int init_pieces()
{
pieces = malloc( num_pieces * sizeof(int) );
return pieces != NULL;
}
Теперь, когда вы включаете свой заголовок, ваш исходный файл будет знать, чтобы получить pieces
откуда-то еще, и будет ожидать, когда компоновщик будет работать там где. Я также предложил функцию init для массива. Однако я не добавил функцию "release".
Обратите внимание, что это все C, а не С++. Если вы используете С++, вы действительно должны использовать new
или еще лучше, используйте vector
.
Кроме того, при использовании статики в С++ помните об этом: статический порядок инициализации С++
Ответ 3
Для высокопроизводительного кода на разных архитектурах вам может понадобиться выделение malloc-y, а не родовое новое. Это связано с тем, что вы могли бы обернуть его чем-то вроде mymalloc(), а затем использовать функции, зависящие от архитектуры, такие как те, которые реализуют правильное выравнивание, чтобы избежать промахов в кеше и выполнять другие отличные вещи, предоставленные производителем оборудования, например IBM (Bluegene) или Intel (MIC). Все эти оптимизированные процедуры распределения имеют структуру типа malloc.