2016-09-07 207 views
0

我有下面的代碼段,這是隻在整個代碼一半:試圖創建一個動態數組

// Declare map elements using an enumeration 
enum entity_labels { 
    EMPTY = 0, 
    WALL 
}; 
typedef entity_labels ENTITY; 

// Define an array of ASCII codes to use for visualising the map 
const int TOKEN[2] = { 
    32,  // EMPTY 
    178  // WALL 
}; 

// create type aliases for console and map array buffers 

using GUI_BUFFER = CHAR_INFO[MAP_HEIGHT][MAP_WIDTH]; 
using MAP_BUFFER = ENTITY[MAP_HEIGHT][MAP_WIDTH]; 

//Declare application subroutines 
void InitConsole(unsigned int, unsigned int); 
void ClearConsole(HANDLE hStdOut); 
WORD GetKey(); 
void DrawMap(MAP_BUFFER & rMap); 


/************************************************************************** 
    * Initialise the standard output console 
    */ 
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 
if (hStdOut != INVALID_HANDLE_VALUE) 
{ 
    ClearConsole(hStdOut); 

    // Set window title 
    SetConsoleTitle(TEXT("Tile Map Demo")); 

    // Set window size 
    SMALL_RECT srWindowRect; 
    srWindowRect.Left = 0; 
    srWindowRect.Top = 0; 
    srWindowRect.Bottom = srWindowRect.Top + MAP_HEIGHT; 
    srWindowRect.Right = srWindowRect.Left + MAP_WIDTH; 

    SetConsoleWindowInfo(hStdOut, true, &srWindowRect); 

    // Set screen buffer size 
    COORD cWindowSize = { MAP_WIDTH, MAP_HEIGHT }; 
    SetConsoleScreenBufferSize(hStdOut, cWindowSize); 
} 
/*************************************************************************/ 


/************************************************************************* 
* Initialise the tile map with appropriate ENTITY values 
*/ 

MAP_BUFFER tileMap; 

for (unsigned int row = 0; row < MAP_HEIGHT; row++) 
{ 
    for (unsigned int col = 0; col < MAP_WIDTH; col++) 
    { 
     tileMap [row][col] = WALL; 
    } 
} 

基本上整個碼被用來創建一個元件地圖並將其輸出到屏幕上,但我試圖在運行時使tileMap成爲一個動態數組。 我已經嘗試在創建tileMap的地方創建一個。 我試過創建一個「entity_lables」之後給出typedef「ENTITY」。 我試過在「MAP_BUFFER」和「GUI_BUFFER」成爲別名後創建一個。 但是我仍然無所適從,我不知道如何成功實現一個動態數組到tileMap,而且我當然不知道把它放在最合適的位置。

任何幫助將不勝感激。

+0

至於我,那我什麼也沒有理解。 –

+0

我不明白這個問題,但我猜你需要的是'std :: vector >' – Mine

+0

我試着將MAP_BUFFER tileMap(朝向代碼底部)更改爲MAP_BUFFER * tileMap =新的MAP_BUFFER,但然後我得到一個「新」的錯誤,說「類型的值」ENTITY(*)[30]「不能用於初始化」MAP_BUFFER *「類型的實體」 – Nick

回答

0

您用於定義數組的語法是用於一個常量大小的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() 

當你在它,你應該看看其他容器,如地圖和集,因爲它們讓你的生活更輕鬆。

編輯:

既然你想知道如何使一個動態數組沒有使用矢量我會給你一個答案:的std :: vector是C++定義動態大小的數組。 C數組在定義後不會改變大小,vector將會。

但是我認爲你在問能否定義運行時常量大小的數組。所以我會解釋他們是什麼以及爲什麼你不應該使用它們。

當您定義C數組時,您可能會收到一條警告,說該表達式需要保持不變。

C數組是指向堆棧的指針。編譯時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 
} 

如果你想使用一個運行時常量數組,我建議標準:數組的容器。它就像矢量一樣管理它的內部存儲器,但是如果你不需要添加新的元素,那麼它是優化的。它的聲明與vector類似,但不包含其構造函數之後的調整大小函數。

+0

感謝所有這一切,我會記住它。 但無論如何可以創建一個新的數組,而不是一個向量? – Nick

+0

編輯我的答案。簡單的答案是肯定的,但是使用C++容器代替:使用std:array或std :: vector通常比自己管理堆更好。 – Gamenotcore