внешняя константа c ++ int для размера массива

У меня есть следующие три файла в моем коде (большая часть кода удалена. Это просто, чтобы изолировать проблему).

global.h:

//global.h
#ifndef GLOBAL_H
#define GLOBAL_H
extern const int ARRAYSIZEX;
extern const int ARRAYSIZEY;
extern const int ARRAYSIZEZ;
#endif //GLOBAL_H

global.cpp:

//global.cpp
#include "global.h"const int ARRAYSIZEX = 5;
const int ARRAYSIZEY = 2;
const int ARRAYSIZEZ = 4;

главный:

//main
#include "global.h"using namespace std;

someType mySomeTypeArray[ARRAYSIZEX][ARRAYSIZEY][ARRAYSIZEZ];

int main(int argc, char **argv)
{
//...
}

Компиляция дает мне три ошибки при объявлении mySomeTypeArray.

ошибка: граница массива не является целочисленной константой перед токеном ‘]’

Я хочу сохранить мои определения глобальной переменной и размера массива в global.h / cpp для этого приложения, просто для организации, чтобы все мои параметры конфигурации были в одном месте. Как правильно добиться того, что я пытаюсь сделать?

Спасибо

3

Решение

Ваше объявление терпит неудачу, потому что размеры массива нужно оценивать во время компиляции, а ваша схема инкапсуляции фактически скрывает значения от компилятора. Это правда, потому что компиляторы работают с отдельными единицами перевода. Во время компиляции main.cpp ваш компилятор видит только extern const int ARRAYSIZEX благодаря include оператор, но не значение, которое видно в отдельном блоке перевода, поэтому он не может определить структуру памяти.

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

global.h

constexpr int ARRAYSIZEX = ...;
constexpr int ARRAYSIZEY = ...;
constexpr int ARRAYSIZEZ = ...;

main.cpp

#include "global.h"someType mySomeTypeArray[ARRAYSIZEX][ARRAYSIZEY][ARRAYSIZEZ];
2

Другие решения

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

Поскольку это определено в другом файле, оно не может. Этот файл должен быть скомпилирован до того, как он узнает, и результат этой компиляции, из-за того, как работает C ++, не может повлиять на компиляцию этого файла.

Вы должны будете объявить это как const int в заголовке, если вы хотите поделиться этими значениями. extern int не будет сокращать это.

Хотя это тривиальный пример, на самом деле нет причин спускаться extern дорога вообще. Просто определите значения в заголовочном файле как обычные const int,

3

Размер массива должен быть указан целочисленным константным выражением. const int Объект может использоваться в выражении целочисленной константы тогда и только тогда, когда он объявлен с помощью инициализатора и этот инициализатор также является выражением целочисленной константы. Ваш ARRAYSIZE... переменные не удовлетворяют этому требованию. В main они объявлены без инициализатора. Вы не можете использовать ARRAYSIZE... переменные как размеры массивов в main,

Если у вас нет особого требования дать этим переменным внешнюю связь, просто объявите (и определите) их в заголовке как

const int ARRAYSIZEX = 5;
const int ARRAYSIZEY = 2;
const int ARRAYSIZEZ = 4;

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

Если действительно хотите дать им внешнюю связь, объявите их как inline extern const в шапке

inline extern const int ARRAYSIZEX = 5;
inline extern const int ARRAYSIZEY = 2;
inline extern const int ARRAYSIZEZ = 4;

поскольку inline само по себе мешает const от навязывания внутренней связи, extern совершенно необязательно в этих декларациях. И с тех пор inline const комбинация может быть заменена на constexpr (как отметил @MM в комментариях), вы можете добиться того же эффекта, просто

constexpr int ARRAYSIZEX = 5;
constexpr int ARRAYSIZEY = 2;
constexpr int ARRAYSIZEZ = 4;
2

Проблема здесь в том, что ARRAYSIZEX, ARRAYSIZEY а также ARRAYSIZEZ не являются константами времени компиляции. Они являются константами — поэтому их значения нельзя изменить, но их значения не известны компилятору.

В C ++ процесс компиляции состоит из 3 основных этапов.

  1. Предварительная обработка всех исходных файлов выполняется препроцессором.
  2. Компиляция для каждой единицы перевода (файл .cpp) выполняется компилятором. Для каждого модуля перевода компилятор создает объектный файл.
  3. Связывание всех объектных файлов осуществляется компоновщиком. Вывод представляет собой исполняемый файл.

В C ++ ключевое слово extern для компилятора означает, что переменная «где-то» определена. Компилятор не знает реальный адрес переменной, но помещает ключевое слово extern Гарантируется, что переменная действительно существует, и компоновщик сможет найти свой адрес по имени при создании исполняемого файла.

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

Решение простое. Используйте уже упоминалось constexpr ключевое слово и инициализировать все переменные с инициализаторами. Ключевое слово constexpr отмечает константы времени компиляции — константы, которые должны быть инициализированы в инициализаторах и известны компилятору.

0
По вопросам рекламы [email protected]