2012-06-04 5 views
2

클래스를 정의하려고합니다. - 할당 된 배열의 첫 번째 차원을 동적 크기를 가질 수C++ 배열 크기 초기화

enum Tile { 
GRASS, DIRT, TREE 
}; 

class Board { 
public: 
    int toShow; 
    int toStore; 
    Tile* shown; 
    Board (int tsh, int tst); 
    ~Board(); 
}; 

Board::Board (int tsh, int tst) { 
    toShow = tsh; 
    toStore = tst; 
    shown = new Tile[toStore][toStore]; //ERROR! 
} 

Board::~Board() { 
    delete [] shown; 
} 

그러나, 나는 표시 줄에 다음과 같은 오류가 발생합니다 : 이것은 내가 가지고있는 것입니다.

내가 할 수 있기를 원하는 것은 오히려 하드 코딩하는 것입니다. 매개 변수 toShow를 생성자에 전달하고 표시하려는 요소 만 포함하는 2 차원 배열을 만듭니다.

그러나 이해해야 할 것은 생성자가 호출되고 표시되는 것이 초기화되면 크기가 toStore의 현재 값으로 초기화된다는 것입니다. 그러면 toStore가 변경 되더라도 메모리는 표시된 배열에 이미 할당되어 있으므로 크기가 변경되지 않아야합니다. 그러나 컴파일러는 이것을 좋아하지 않습니다.

내가 이것을 어떻게 이해하고 있는지에 대한 오해가 있습니까? 누구든지 배열의 크기로 하드 코드하지 않고도 원하는대로 할 수정 프로그램이 있습니까? 당신이 2 차원 배열을 참조 할 경우

+2

우선, 2D 포인터가 필요합니다 : '타일 ** 표시됨'. 조금만 읽어보십시오. 어떻게하는지 배웠다면 대신'std :: vector'를 사용하십시오. – chris

+3

http://ideone.com/gytw7 –

+0

@ R.MartinhoFernandes, 나는 당신이 묘사 한 이유 때문에 그 일에 열심히 노력해야 만했습니다. 나는 한 번에 한 번씩 C 스타일의 가변 인자로 내 자신의 'xarray'를 만들었다. – chris

답변

3

C++의 컨테이너를 사용하십시오. 그 컨테이너가있는 것입니다.

class Board { 
public: 
    int toShow; 
    int toStore; 
    std::vector<std::vector<Tile> > shown; 
    Board (int tsh, int tst) : 
     toShow(tsh), toStore(tst), 
     shown(tst, std::vector<Tile>(tst)) 
    { 
    }; 
}; 

... 

    Board board(4, 5); 
    board.shown[1][3] = DIRT; 
+1

감사합니다. 배열을 가지고 할 수있는 방법이 있는지 궁금 해서요.하지만 이제 벡터를 사용하여 내 인생을 훨씬 쉽게 만들어주었습니다. 사실 1D 배열의 벡터를 사용하기로 결정했습니다. – user1413793

0

첫째, 당신은 포인터에 대한 포인터를 선언해야 :

다음
Tile **shown; 

는 오류 메시지를 보라. 그것은 적절하고 이해하기 쉬운 영어입니다. 그것은 오류가 무엇인지 말해줍니다. Only the first dimension of an allocated array can have dynamic size. 의미 - 할당 된 배열의 첫 번째 차원 만 동적 크기를 가질 수 있습니다. 그게 전부 야. 행렬에 여러 개의 동적 치수가 있도록하려면 C 스타일 malloc()을 사용하여 포인터에 대한 포인터를 유지하거나 C++에 대해 더 나은 포인터 인 vector을 사용하십시오.

+1

'new * [SIZE]'가'malloc'보다 나은가요? – chris

+0

'foo (int [3] [4] a)','foo (int [3] [] a)'모두 유효합니다. (아니면 어쩌면 기억이 안나요.) – djechlin

+0

@ H2C03 절대 쓸모없고 무례한 말에 감사드립니다. 네, 저는 평범한 영어를 읽을 수는 있지만 어쩌면 당신은 내 질문을 완전히 오독했기 때문에 캔트 할 수 있습니다. 당신이 내가 물었던 것에 대한 답을 찾을 수 없기 때문에 당신이 분노했다는 것을 이해할 수 있습니다. 아니면 당신이 방금 물었던 것을 이해하지 못했을 것입니다. 아마 당신의 무례 함을 설명 할 수도 있습니다. 내 시간을 낭비 해줘서 고마워. – user1413793

0

C 및 C++에서 메모리 할당이 어떻게 작동하는지 조금 이해하면 좋습니다.

char x[10]; 

컴파일러는 아마도 그것은 0x12에있어, 시작 주소를 열 바이트를 할당하고 기억할 것입니다 (실제 생활에서 아마 훨씬 더 많은 수의.)

x[3] = 'a'; 

지금 컴파일러가를 복용하여 x[3]를 찾습니다 x의 시작 주소는 0x12이고 3*sizeof(char)을 추가하면 0x15이됩니다. 따라서 x[3]0x15에 있습니다.

이 간단한 덧셈 - 산술은 배열 내부의 메모리에 액세스하는 방식입니다. 2 차원 배열의 경우 수학은 약간 까다 롭습니다. 어떤 장소에서 시작

char xy[20][30]; 

를 할당 600 바이트, 어쩌면 0x2000입니다. 이제 xy[0][0], xy[0][1], xy[0][2]...는 처음 30 바이트를 차지하려고 ...

xy[4][3]; 

일부 수학을 필요 접근. 그런 다음 xy[1][0], xy[1][1], ...은 31-60 바이트를 차지합니다. 곱셈입니다. 은 xy의 주소에 * 20, 더하기 b가 있습니다.

이것은 컴파일러가 첫 번째 차원의 길이를 알고있는 경우에만 가능합니다. 컴파일러가이 계산을 수행하기 위해 숫자 "20"을 알아야한다는 것을 알게됩니다.

이제 함수 호출. 당신이

foo(int* x); 

또는

foo(int[] x); 

두 경우 모두에서 바이트의 배열이기 때문에

를 호출 여부를 컴파일러는 작은 배려, 당신은 시작 주소를 전달하고 컴파일러에서 장소를 찾기 위해 추가 작업을 수행 할 수 있습니다 어떤 x[3] 또는 무엇이든 살고있다. 그러나 2 차원 배열의 경우 컴파일러는 위의 예에서 해당 마법 번호 20을 알아야합니다. 그래서

foo(int[][] xy) { 
    xy[3][4] = 5;  //compiler has NO idea where this lives 
         //because it doesn't know the row dimension of xy! 
} 

는하지만

foo(int[][30] xy) 

를 지정하면 컴파일러는 무엇을 알고있다. 이유는 더블 포인터로 전달하는 것이 더 나은 방법이라고 종종 생각할 수는 없지만, 기술 수준에서 진행되는 것입니다.

+0

감사합니다. 그것은 훨씬 더 의미가 있습니다. – user1413793

2

1 차원 배열을 사용할 수 있습니다. 2 차원 배열은 1 차원 배열로 취급되며 가변 크기를 원하면이 패턴을 사용할 수 있음을 알아야합니다. 예 :

int arr1[ 3 ][ 4 ] ; 
int arr2[ 3 * 4 ] ; 

들은 동일하며, 그 구성원은 서로 다른 부호를 통해 접근 될 수있다 : 물론 arr1의

int x = arr1[ 1 ][ 2 ] ; 
int x = arr2[ 1 * 4 + 2 ] ; 

은 3 행 × 4 COLS 행렬로 간주 될 수 있고 3 COLS × 4 행 행렬. 이 유형의 다차원 배열을 사용하면 단일 포인터를 통해 액세스 할 수 있지만 내부 구조에 대해 알아야합니다. 그것들은 2 차원 또는 3 차원으로 취급되는 1 차원 배열입니다.

+0

도움에 감사드립니다. 이것은 내가 이해하려고 노력한 것입니다. – user1413793

+0

당신을 진심으로 환영합니다. 나는 당신이 이것으로 OK가 아니면 더 많은 설명을 추가 할 수있다. –

1

3D 배열이 필요할 때 내가 한 일에 대해 알려 드리겠습니다. 그것은 과도한 부담일지도 모르지만, 그것은 당신이 원하는 것을하는 완전히 다른 방법이지만 다소 차갑고 도움이 될 것입니다.

세포의 3D 상자를 표현해야했습니다. 세포의 일부분 만 표시되었고 관심이있었습니다. 이를 수행하기위한 두 가지 옵션이있었습니다. 첫 번째는 가능한 가장 큰 크기의 정적 3D 배열을 선언하고 상자의 하나 이상의 치수가 정적 배열의 해당 치수보다 작은 경우 해당 부분을 사용합니다.

두 번째 방법은 배열을 동적으로 할당하고 할당을 해제하는 것이 었습니다. 3D는 말할 것도없고 2D 배열로도 상당히 효과적입니다.

어레이 솔루션은 특별한 가치를 지닌 관심 세포를 가진 3D 어레이를 정의했습니다. 할당 된 메모리의 대부분은 불필요했습니다.

두 가지 방법으로 버려졌습니다. 대신 나는 STL지도를 사용했다. 좌표를 나타내는 x, y, z 3 개의 멤버 변수가있는 Cell이라는 구조체를 정의합니다. 그러한 셀을 쉽게 생성하기 위해 생성자 Cell(x, y, z)이 사용되었습니다. operator <을 주문할 수 있도록 정의했습니다. 그런 다음 map<Cell, Data>을 정의했습니다.좌표 X, Y에 표시된 셀을 추가,지도에 Z는

my_map[Cell(x, y, z)] = my_data;

나는 3D 배열의 메모리 관리를 유지하기 위해, 또한 오직 필요한 세포가 실제로 만들어진 필요하지 않은이 방법에 의해 간단하게 이루어졌다 .

이 호출에서 X0, Y0 좌표 경우, Z0가 존재 확인 중 (또는 표시)에 의해 수행되었다 : my_map[Cell(x0, y0, z0)]...

:

map<Cell, Data>::iterator it = my_map.find(Cell(x0, y0, z0)); 
if (it != my_map.end()) { ... 

그리고 번호 좌표 X0에서 셀의 데이터를 참조, Y0는 Z0는에 의해 수행되었다

이 약물은 이상하게 보일 수 있지만 견고하고 자기 관리로 기억에 관련되며 안전합니다. 경계 오버런이 없습니다.