Определение статического массива в исходном файле C или С++
Я знаю, что это вопрос, который должен знать каждый программист, но я не знаю. Долгое время не программирование на С, и я забыл многое.
Мой вопрос:
У меня есть три огромных статических массива, определенных внутри файла заголовка. Кто-то сказал мне, что гораздо лучше объявить их как extern
в файле заголовка и определить их в одном исходном файле C или С++.
Как я могу это сделать?
Вот мой заголовочный файл:
#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_
#define NUM_TEMPLE_OBJECT_VERTEX 10818
static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
static const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
#endif
Если использовать исходный файл С++, может мне нужно определить класс?
ОБНОВЛЕНИЕ:
Я думаю, что проблема заключается в следующем:
Каждый исходный файл, в который включены эти заголовки (даже косвенно), будет генерировать собственное определение для этих статических массивов. Там нет гарантии, что компилятор/компоновщик будет оптимизировать их в одном определении, даже в исходных файлах, где они не используются. Фактически, во многих случаях компилятор не может их оптимизировать. Это может привести к тому, что ваши статические данные будут потреблять много места на диске и, возможно, также память времени выполнения.
Спасибо.
Ответы
Ответ 1
static
и extern
в то же время не имеет смысла. static
в области файлов делает массив недоступным для других файлов, а extern
сообщает компилятору, что ваш массив определен где-то в другом месте.
Вы можете сделать то, что предлагает 321008, за исключением того, что вы не объявляете свои статические массивы, которые являются незаконными C и С++. Это дает вам три глобальных переменных, которые можно использовать везде, где включен заголовочный файл.
Например, например:
// .h file:
extern const float TEMPLEVertices[];
// .cpp (or .c) file:
const float TEMPLEVertices[] = { 1.0, 2.0, 5.6 /* or whatever*/ };
Или вы можете сделать то, что предлагает fortran, но это даст вам доступ к области доступа к файлу, а не глобальные переменные.
Вы никоим образом не должны определять класс, если используете исходный файл С++. В отличие от Java, С++ не принуждает вас к объектно-ориентированному дизайну (можно ли это хорошо обсуждать или нет, но в любом случае).
EDIT: что касается вашего обновления вопроса, это потому, что вы определяете их как static
. Если вам нужны только глобальные переменные, вы не должны этого делать, но вместо этого сохраняйте одно определение (const float
) и ссылайтесь на него с помощью extern
, как в моем примере выше.
Ответ 2
Я однажды увидел в исходном коде Quake2 забавный "трюк", который на самом деле был просто необычным способом использования include:
просто выполните:
static const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {
#include "TEMPLEVertices.txt"
};
и др.
И сохраняйте только данные во входящих файлах.
Вы все равно можете объявить их как extern
в модуле компиляции, но это немного улучшит ситуацию.
Ответ 3
Это очень просто, на самом деле; Я продемонстрирую более простой пример простой примитивной константы.
В вашем проекте у вас есть два файла pi.h
и pi.cpp
.
Содержимое pi.h
выглядит следующим образом:
#ifndef _PI_H
#define _PI_H
extern const double PI;
#endif
Концы pi.cpp
выглядят следующим образом:
#include "pi.h"
const double PI = 3.1415926535;
Если вы хотите использовать эту константу, вы просто включаете pi.h
, где это необходимо. Значение всегда будет считано из того же места.
То же самое можно сделать с почти чем угодно: массивами, объектами, массивами объектов, контейнерами STL и т.д. Просто не забудьте использовать эту технику, особенно если объявленные объекты extern
не const
, вы можете создать некоторые действительно трудно отслеживать побочные эффекты. Но для постоянных данных это вы делаете.
Ответ 4
Ваш заголовочный файл будет выглядеть следующим образом:
#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_
#define NUM_TEMPLE_OBJECT_VERTEX 10818
extern const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3];
extern const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3];
#endif
Пока ваш исходный файл будет выглядеть следующим образом:
// include header
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLENormals[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
const float TEMPLETexCoords[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...};
// rest of the source
Обновление. Если вы явно указываете массивы, вам не нужно указывать размеры. То есть вы можете:
const float TEMPLEVertices[] = {...};
или
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3];
Ответ 5
Обычно я использую простой трюк.
a) В каждом файле C/CPP я определяю filename_C
b) В каждом файле H/HPP я определяю filename_H
чем...
Это будет ваш файл include
#ifndef _TEMPLE_OBJECT_H_
#define _TEMPLE_OBJECT_H_
#define NUM_TEMPLE_OBJECT_VERTEX 10818
#ifdef _TEMPLE_OBJECT_C
const float TEMPLEVertices[NUM_TEMPLE_OBJECT_VERTEX * 3] = {...} ; /* Put here your const values */
#else
extern const float TEMPLEVerticies[] ;
#endif
#endif
Если я не ошибаюсь, то это работает (или что-то очень похожее на это)...: o)