Синтаксис, используемый для определения вашего массива, предназначен для массива C с постоянным размером. В общем случае вы должны уклоняться от массивов C, если размер данных не определяется во время компиляции (и никогда не нужно изменять), и массив никогда не покидает область действия (поскольку массив C не сохраняет информацию по своему размеру.)
Вместо постоянных или динамически массивных массивов C я предлагаю использовать контейнер Vector. Вектор представляет собой динамически размер контейнер, который заполняется со спины, последний элемент, который вы добавили к
std::vector<std::vector<ENTITY>>
Чтобы добавить вектор контейнер для вашего проекта добавить строку
#include <vector>
Для заполнения контейнера ваш цикл может выглядеть следующим образом:
MAP_BUFFER tileMap;
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
std::vector<ENTITY> column; // A column of the tile map
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
column.push_back(WALL); // Add one element to the column
}
tileMap.push_back(column); // Add the column to the tile map
}
или вы можете инициализировать вектор для размера вы хотите в начале и использовать текущий цикл, чтобы присвоить значение плитки:
using TILE_MAP = vector<vector<ENTITY>>;
// MAP_WIDTH x MAP_HEIGHT multidimensional vector
TILE_MAP tileMap(MAP_WIDTH, vector<ENTITY>(MAP_HEIGHT));
for (unsigned int row = 0; row < MAP_HEIGHT; row++)
{
for (unsigned int col = 0; col < MAP_WIDTH; col++)
{
tileMap [row][col] = WALL;
}
}
Вызов элемента вектора после его заполнения имеет тот же синтаксис, что и массив.
tileMap[2][4]
Вы также можете проверить длину вектора:
int rows = tileMap.size();
if(rows > 0)
int columnsInRow0 = tileMap[0].size()
Пока вы на него, вы должны смотреть в другие контейнеры, как Карты и наборы, так как они делают вашу жизнь проще.
Edit:
Так как вы хотите, чтобы узнать, как сделать динамический массив не используя вектор Я дам вам ответ: станд :: вектор является C++ определен массив динамически размера. C массивы не изменят размер после того, как они определены, вектор будет.
Однако, я думаю, вы спрашиваете о возможности определять массивы с постоянным размером времени выполнения. Поэтому я объясню, что это такое и почему вы не должны их использовать.
Когда вы определяете массив C, вы, вероятно, получаете предупреждение о том, что выражение должно быть постоянным.
A C массив - это указатель на стек. И реализация массива compiletime C заключается в том, что во время компиляции он должен быть постоянным.
int compiletimeArray[] = { 1, 2, 3 };
// turns out c arrays are pointers
int* ptr = compiletimeArray;
// prints 2
std::cout << compiletimeArray[1];
// prints 2
std::cout << ptr[1];
// prints 2
std::cout << *(compiletimeArray + 1);
// also prints 2
std::cout << *(ptr + 1); //move pointer 1 element and de-reference
Указатели напоминают доску с номером телефона, написанным на ней. Такие же проблемы возникают, как и в случае телефонных номеров; число на доске было стерто, число на доске изменилось, получатель не существует, получатель изменил свой номер, у провайдера услуг, заканчивающегося доступными номерами, чтобы дать новых пользователей ... Имейте это в виду.
Чтобы создать массив с постоянным размером времени выполнения, вам необходимо выделить массив в куче и назначить его указателю.
int size = 4;
int* runtimeArray = new int[size]; // this will work
delete[] runtimeArray; // de-allocate
size = 8; // change size
runtimeArray = new int[size]; // allocate a new array
Основное различие между стека и кучи, что стек будет де-выделить память, используемую переменной, когда программа выходит из сферы переменная была объявлена, с другой стороны, все, объявленного в куче все равно останется в памяти и должен быть явно выделен или вы получите утечку памяти.
// You must call this when you are never going to use the data at the memory address again
// release the memory from the heap
delete[] runtimeArray; // akin to releasing a phone number to be used by someone else
Если вы не освободите память из кучи, в конце концов вы закончите.
// Try running this
void crashingFunction() {
while(true)
{
// every time new[] is called ptr is assigned a new address, the memory at the old address is not freed
// 90001 ints worth of space(generally 32 or 64 bytes each int) is reserved on the heap
int* ptr = new int[90001]; // new[] eventually crashes because your system runs out of memory space to give
}
}
void okFunction() {
// Try running this
while(true)
{
// every time new[] is called ptr is assigned a new address, the old is not freed
// 90001 ints worth of space is reserved on the heap
int* ptr = new int[90001]; // never crashes
delete[] ptr; // reserved space above is de-allocated
}
}
Зачем использовать std :: vector? Поскольку std :: vector внутренне управляет массивом времени выполнения.
// allocates for you
vector(int size) {
// ...
runtimeArray = new runtimeArray[size];
}
// When the vector exits scope the deconstructor is called and it deletes allocated memory
// So you do not have to remember to do it yourself
~vector() {
// ...
delete[] runtimeArray;
}
Так что, если вы имели один и тот же сценарий, что и в прошлый раз
void vectorTestFunction() {
// Try running this
while(true)
{
std::vector<int> vec(9001); // internally allocates memory
} // <-- deallocates memory here because ~vector is called
}
Если вы хотите использовать во время выполнения постоянного массива я предлагаю зЬй: контейнер массива. Это похоже на вектор, поскольку он управляет своей внутренней памятью, но оптимизирован для того, чтобы вам никогда не приходилось добавлять новые элементы. Он объявлен как вектор, но не содержит функции изменения размера после его конструктора.
Что касается меня, то я ничего не понял. –
Я не понимаю вопроса, но я думаю, что вам нужен 'std :: vector>' –
Mine
Я пробовал изменять MAP_BUFFER tileMap (в нижней части кода) в MAP_BUFFER * tileMap = новый MAP_BUFFER, но затем я получаю сообщение об ошибке «новый», в котором говорится: «Значение типа« ENTITY (*) [30] »не может использоваться для инициализации объекта типа« MAP_BUFFER * »« – Nick