2017년 8월 3일 목요일

C++ 2차원 포인터(포인터의 포인터)를 이용한 2차원 배열 다루기





본 프로그램은 n명의 학생 각각이 m개의 과목을 수강할 경우에 대한 
2차원 배열을 선언하는 형태인데 학생 수가 고정되어 있지 않고 가변이고
각 학생의 수강 과목도 고정되어 있지 않고 각각 상이하다고 할 때의 
상황이다. 이때 가장 적합한 2차원 배열의 형태가 "2차원 포인터(포인터의 포인터)"
형태로 선언하는 것에 대한 예제 코드이다.

#include <iostream>
#include <malloc.h>

using namespace std;

void main()
{
//2차원 포인터는 2차원 배열의 형태를 갖는데 
//세로(행, row)도 가변적인 배열, 가로(열, column)도 가변의 크기를 갖는 배열이라는 뜻
int** score;
int studentNum = 0;
int lessonNum = 0;
int allTotalSize = 0;

cout << "학생 수 입력 : ";
cin >> studentNum;

//studentNum 갯수 만큼의 크기를 가진 배열이 선언되는데 이 배열의 각 원소가
//int형 포인터 변수이므로 각 원소가 또 동적 할당으로 임의 크기의 배열의 시작 주소를
//가리키게 되므로 결국 2차원 배열이 되는 것이다.
//즉 studentNum 갯수 만큼의 크기를 가진 int형 포인터 변수가 배열 형태로
//선언되고 그 시작 주소 값을 score에 저장한다.
//통상적으로 이렇게 생성되는 배열을 2차원 배열의 행(row, 가로)의 크기로 본다.
score = new int*[studentNum];
cout << "sizeof(score) : " << sizeof(score) << " byte" << endl;
cout << "_msize(score) : " << _msize(score) << " byte" << endl << endl;

//_msize()함수에 대해: new로 생성된 메모리는 heap 메모리 영역에 생성되고
//heap 메모리 영역은 운영체자가 관리해 주기 때문에 동적 할당된 메모리의 크기를
//알기 위해서는 운영체제의 도움이 필요하다.
//윈도우의 경우 _msize()함수를 통해 알수 있다.
//반면에 sizeof()함수는 포인터 변수 자체의 크기를 반환하는데 포인터 변수는 
    //항상 4byte로 동일하다
//아래의 코드는 score가 가리키는 동적 할당된 메모리 전체의 크기를 반환한다.
//score = new int*[studentNum]으로 할당되었기에 
//studentNum * 4(int형의 크기가 4byte이므로)의 크기를 가진다.
allTotalSize = _msize(score);

//studentNum 갯수 만큼의 배열 각 요소인 int형 포인터 변수 각각에 대해
//동적 메모리 할당을 통해 또 다시 배열을 만든다. 따라서 2차원 배열이 되는 것이다.
//통상적으로 이렇게 생성되는 배열을 2차원 배열의 열(column, 세로)의 크기로 본다.
for (int i = 0; i < studentNum; i++)
{
cout << (i+1) << "번 학생의 수강 과목 수 : ";
cin >> lessonNum;

score[i] = new int[lessonNum];
allTotalSize += _msize(score[i]);
cout << (i + 1) << "번째 배열의 크기 : " << _msize(score[i]) << " byte" 
                                                                                            << endl << endl;
}

cout << endl << "2차원 포인터 배열 전체의 크기 : " << allTotalSize << " byte" 
                                                                                            << endl;

//여기서 성적 입력 및 평균, 총점 처리...

//메모리 해제(동적 할당된 메모리는 사용후 반드 해재해 줘야함!)
for (int i = 0; i < studentNum; i++)
{
delete[] score[i];
//delete score[i]; //이 경우는 i번째 배열 전체가 아닌 그 배열의 시작 주소만 해제 함
}

delete[] score;

cout << endl << "동적 할당 메모리 해제 완료~" << endl;
}

실행 결과는 다음과 같다.



댓글 없음:

댓글 쓰기