1

스택 오버플로 오류에 대한 이전 질문이 있고 개체 배열에 대한 벡터로 전환합니다. 이 질문은 필요한 경우 여기에서 참조 할 수 있습니다. How to get rid of stack overflow error벡터 초기화 속도를 높이는 방법 C++

그러나 현재의 질문은 벡터의 초기화 속도를 높이는 것입니다. 내 현재 방법은 현재 ~ 15 초 걸립니다. 벡터 대신 배열을 사용하면 배열 오버플로 오류가 발생하지 않는 크기의 배열로 초 걸렸습니다. MAIN.CPP에서

나는 나의 던전 개체 초기화 : 여기

내가 그것을 초기화하고 어떻게 내 던전에

dungeon = Dungeon(0, &textureHandler, MIN_X, MAX_Y); 

을 (...) 생성자, 나는 객실 내 5 * 5 벡터를 초기화 및 loadDungeon 전화 :

:

Dungeon::Dungeon(int dungeonID, TextureHandler* textureHandler, int topLeftX, int topLeftY) 
{ 
    currentRoomRow = 0; 
    currentRoomCol = 0; 
    for (int r = 0; r < MAX_RM_ROWS; ++r) 
    { 
     rooms.push_back(vector<Room>()); 
     for (int c = 0; c < MAX_RM_COLS; ++c) 
     { 
      rooms[r].push_back(Room()); 
     } 
    } 
    loadDungeon(dungeonID, textureHandler, topLeftX, topLeftY); 
} 

내 방 생성자는 세포 (그래서 나는 loadDungeon 함수를 설정할 수 있습니다) 내 30 × 50 벡터를 채 웁니다 17,451,515,

Room::Room() 
{ 
    for (int r = 0; r < MAX_ROWS; ++r) 
    { 
     cells.push_back(vector<Cell>()); 
     for (int c = 0; c < MAX_COLS; ++c) 
     { 
      cells[r].push_back(Cell()); 
     } 
    } 
} 

내 디폴트의 셀 생성자는 간단하고 많은 일을하지 않고, 어쨌든 그것을 게시합니다 :

Cell::Cell() 
{ 
    x = 0; 
    y = 0; 
    width = 16; 
    height = 16; 
    solid = false; 
    texCoords.push_back(0); 
    texCoords.push_back(0); 
    texCoords.push_back(1); 
    texCoords.push_back(0); 
    texCoords.push_back(1); 
    texCoords.push_back(1); 
    texCoords.push_back(0); 
    texCoords.push_back(1); 
} 

그리고 마지막으로 내 loadDungeon() 함수는 세포를 설정합니다. 결국이 파일에서 읽고 셀을로드 할 수 있지만 지금 가능한 경우이 비트를 최적화하고 싶습니다.

void Dungeon::loadDungeon(int dungeonID, TextureHandler* textureHandler, int topLeftX, int topLeftY) 
{ 
    int startX = topLeftX + (textureHandler->getSpriteWidth()/2); 
    int startY = topLeftY - (textureHandler->getSpriteHeight()/2); 
    int xOffset = 0; 
    int yOffset = 0; 
    for (int r = 0; r < MAX_RM_ROWS; ++r) 
    { 
     for (int c = 0; c < MAX_RM_COLS; ++c) 
     { 
      for (int cellRow = 0; cellRow < rooms[r][c].getMaxRows(); ++cellRow) 
      { 
       xOffset = 0; 
       for (int cellCol = 0; cellCol < rooms[r][c].getMaxCols(); ++cellCol) 
       { 
        rooms[r][c].setupCell(cellRow, cellCol, startX + xOffset, startY - yOffset, textureHandler->getSpriteWidth(), textureHandler->getSpriteHeight(), false, textureHandler->getSpriteTexCoords("grass")); 
        xOffset += textureHandler->getSpriteWidth(); 
       } 
       yOffset += textureHandler->getSpriteHeight(); 
      } 
     } 
    } 

    currentDungeon = dungeonID; 
    currentRoomRow = 0; 
    currentRoomCol = 0; 
} 

그래서 속도를 올리면 매회로드하는 데 약 15 초가 걸릴 수 있습니다. 간단한 2D 게임을로드하는 데 15 초가 걸리지 않아야한다고 생각합니다.

솔루션 그럼 내 솔루션 내 코드에 표준 : : 벡터 : 예약 전화 (rooms.reserve를 사용하는 것이었다 그리고 그것은 잘 작동하고 끝났다. 나는 던전 내 기능 던전 :: loadDungeon을 변경 :: loadDefaultDungeon을하기 때문에 . 지금 여기 어쨌든

을 저장 파일을로드 (내가 디버그 모드에서 15 + 초 ~에서 4 ~ 5 초에 내려 있어요) 코드입니다 : 그것은 보인다 때문에

Dungeon::Dungeon() 
{ 
    rooms.reserve(MAX_RM_ROWS * MAX_RM_COLS); 
    currentDungeon = 0; 
    currentRoomRow = 0; 
    currentRoomCol = 0; 
} 
void Dungeon::loadDefaultDungeon(TextureHandler* textureHandler, int topLeftX, int topLeftY) 
{ 
    int startX = topLeftX + (textureHandler->getSpriteWidth()/2); 
    int startY = topLeftY - (textureHandler->getSpriteHeight()/2); 
    int xOffset = 0; 
    int yOffset = 0; 
    cerr << "Loading default dungeon..." << endl; 
    for (int roomRow = 0; roomRow < MAX_RM_ROWS; ++roomRow) 
    { 
     for (int roomCol = 0; roomCol < MAX_RM_COLS; ++roomCol) 
     { 
      rooms.push_back(Room()); 
      int curRoom = roomRow * MAX_RM_COLS + roomCol; 
      for (int cellRow = 0; cellRow < rooms[curRoom].getMaxRows(); ++cellRow) 
      { 
       for (int cellCol = 0; cellCol < rooms[curRoom].getMaxCols(); ++cellCol) 
       { 
        rooms[curRoom].setupCell(cellRow, cellCol, startX + xOffset, startY - yOffset, textureHandler->getSpriteWidth(), textureHandler->getSpriteHeight(), false, textureHandler->getSpriteTexCoords("default"), "default"); 
        xOffset += textureHandler->getSpriteWidth(); 
       } 
       yOffset += textureHandler->getSpriteHeight(); 
       xOffset = 0; 
      } 
      cerr << "  room " << curRoom << " complete" << endl; 
     } 
    } 
    cerr << "default dungeon loaded" << endl; 
} 

Room::Room() 
{ 
    cells.reserve(MAX_ROWS * MAX_COLS); 
    for (int r = 0; r < MAX_ROWS; ++r) 
    { 
     for (int c = 0; c < MAX_COLS; ++c) 
     { 
      cells.push_back(Cell()); 
     } 
    } 
} 
void Room::setupCell(int row, int col, float x, float y, float width, float height, bool solid, /*std::array<float, 8>*/ vector<float> texCoords, string texName) 
{ 
    cells[row * MAX_COLS + col].setup(x, y, width, height, solid, texCoords, texName); 
} 

void Cell::setup(float x, float y, float width, float height, bool solid, /*std::array<float,8>*/ vector<float> t, string texName) 
{ 
    this->x = x; 
    this->y = y; 
    this->width = width; 
    this->height = height; 
    this->solid = solid; 
    for (int i = 0; i < t.size(); ++i) 
     this->texCoords.push_back(t[i]); 
    this->texName = texName; 
} 
+0

최적화를 사용하여 컴파일 중입니까? 표준 라이브러리 컨테이너는 _ 템플릿이며 컴파일러 최적화로 인해 많은 이점을 얻습니다. – Blastfurnace

+0

@Blastfurnace 어떻게 켜는거야? – Steven

+1

스트라이드에서 액세스되는 평면 1 차원 벡터를 사용해보십시오. 또한, 충분한 공간을 '예비'합니다. –

답변

3

그것은 너무 많은 동적 할당을 가지고 낭비 보인다는 같은 일을 수행 할 수 있습니다. 당신은 당신의 벡터를 평평하고 진보에 액세스하여 하나 개의 할당 멀리 얻을 수 있습니다 :

resize은 하나의 할당뿐만 아니라 각 요소를 기본적 구성을 초래, 정확히 한 번만 수행하는 방법을
std::vector<Room> rooms; 

rooms.resize(MAX_RM_ROWS * MAX_RM_COLS); 

for (unsigned int i = 0; i != MAX_RM_ROWS; ++i) 
{ 
    for (unsigned int j = 0; j != MAX_RM_COLS; ++j) 
    { 
     Room & r = rooms[i * MAX_RM_COLS + j]; 
     // use `r`  ^^^^^^^^^^^^^^^^^^^-----<< strides! 
    } 
} 

참고. 오히려 각 요소를 구체적으로 구성하려면 rooms.reserve(MAX_RM_ROWS * MAX_RM_COLS);을 대신 사용하고 루프에서 벡터를 채 웁니다.

또한 행과 열을 바꿔서 프로파일 링하고 어떤 것이 더 빠르는지 확인할 수 있습니다.

+0

어쨌든 당신은 '방 & r = 객실 [i * MAX_RM_COLS + j];' 조금 더? 거기에서 무슨 일이 일어나고 있는지 확실하지 않습니다. – Steven

+0

@Flappy : 저는 하나의 카운터로 2 차원 공간을 열거했습니다. 행에 따라 행을 옮겨 사각형으로 셀을 셀 수있는 방법입니다. –

+0

내가 이것을 찔러 보자 ... 그 라인에 도달하면 현재 열 위치를 가리키는 'r'이라는 새 공간을 만들고 있습니다. [i * MAX_RM_COLS + j] 0-4의 결과는 행 0에 있고, 5-9는 1 행에있는 식입니다. 따라서 2D 배열처럼 작동합니다. 배열에서 방을 조작하기 위해 'r'을 사용하겠습니까? 예 : r = Room(); (기본 init의 경우)? 내가 통과 했습니까? lol – Steven

3

당신의 벡터는 컴파일시에 크기가 정의되어 있으므로 C++ 11을 사용할 수 있다면을 사용하는 것이 좋습니다 std::vector 대신입니다. std::array은 크기를 조정할 수 없으며 std::vector의 작업이 많지 않지만 훨씬 가볍습니다. 현재 수행중인 작업에 적합합니다.

#include <array> 

/* ... */ 

std::array<std::array<Cell, MAX_COLS>, MAX_ROWS> cells; 

UPDATE : 로컬 보낸std::array는 스택 내부 배열을 할당 정의는 OP이 스택 오버플로가 발생할 것이다 인해 상당히 큰로서 예로서

하면 cells를 선언 할 배열의 크기. 여전히 힙에 배열을 할당하여 std::array (및 그 이점은 std::vector을 사용하는 것에 비해 이점)을 사용할 수 있습니다.

더 나은
typedef std::array<std::array<Cell, MAX_COLS>, MAX_ROWS> Map; 
Map* cells; 

/* ... */ 

cells = new Map(); 

, 스마트 포인터를 사용할 수 있습니다 :

#include <memory>  

/* ... */ 

std::unique_ptr<Map> cells; 
cells = std::unique_ptr(new Map()); 
+0

처음 질문에 언급했듯이 배열을 사용하여 스택 오버플로 오류가 발생합니다. – Steven

+0

@Flappy C++ 11 배열 또는 일반 C 유사 배열을 사용하고 있었습니까? 그들은 완전히 다른 것들입니다. – betabandido

+0

@Flappy 일반 C와 같은 배열은 객체가 아니라 데이터 유형입니다. 'std :: array'는'std :: vector'처럼 STL 클래스입니다 만, 배열의 크기는 벡터의 경우처럼 동적으로 바꿀 수 없습니다. 'std :: array'는 최근에 C++ 11에서 소개되었으므로 비교적 새로운 컴파일러가 필요합니다. 여기에 [새로운 C++ 11 기능] (http://en.wikipedia.org/wiki/C%2B%2B11)에 대한 설명이 있습니다. 답에서'std :: array'를 설명하는 링크를 찾을 수 있습니다. – betabandido

관련 문제