Chapter 4. 복합 데이터형 - new를 사용한 동적 구조체의 생성

SeungHee Yun·2022년 7월 16일
0

C++ 기초 플러스

목록 보기
16/115

new를 사용한 동적 구조체의 생성


컴파일 시간 보다는 실행 시간에 배열을 생성하는 것이

훨씬 유리하다는 것을 알아보았다.

이것은 구조체도 해당된다. new를 구조체에 사용할 때에는 두 가지를 알아야한다.

하나는 구조체를 생성하는 것이고, 다른 하나는 구조체 멤버에 접근하는 것이다.

다음 예시를 보자


inflatable* ps = new inflatable;

이 코드는, inflatable 형의 구조체를 저장할 수 있는 크기의

새로운 메모리 블록을 확보하고, 주소를 ps에 대입한다.

멤버에 접근하는 것은 약간 까다롭다.

동적 구조체에는 도트(.) 멤버 연산자 사용이 불가하기 때문이다.

C++는 이 문제를 해결하기 위해, 화살표 멤버 연산자 ( -> )를 사용한다.

도트 멤버 연산자는 구조체 이름과 함께 사용하고,

화살표 멤버 연산자는 구조체를 지시하는 포인터와 사용한다.

예를 들어, ps가 inflatable형 구조체를 지시하는 포인터라면,

ps -> price는, ps가 지시하는 구조체의 price 멤버이다.


구조체 멤버에 접근하는 다소 보기 흉한 다른 방법은,

*ps가 포인터가 지시하는 값, 즉 구조체이기 때문에

(*ps)처럼 괄호를 붙여 사용하는 방법이다.

inflatable* ps = new inflatable;
ps -> name;		// 멤버에 접근하는 제 1 방법
(*ps).name; 	// 멤버에 접근하는 제 2 방법

new와 delete를 사용하는 예제


프로그램이 1,000개의 문자열을 읽어들여야 한다고 가정하자.

그 중에서, 가장 긴 문자열은 79개의 문자이지만,

대부분의 문자열은 그보다 길이가 훨씬 짧다.

문자열 저장을 위해 char 형의 배열을 사용하면,

크기가 80인 char형의 배열을 1,000개나 만들어야 한다.

이를 위해선 전체 80,000 바이트가 필요하다.

이렇게 할 경우, 대부분의 메모리 공간은 사용되지 않고 버려진다...

좋은 대안은,

char형을 지시하는 1,000개의 포인터를 원소를 가지는 배열을 만드는 것이다.

문자열마다 new를 사용하여, 각 문자열의 크기에 맞는 메모리 블록을 대입하고,

각 블록의 주소는 포인터 배열의 각 원소에 대입한다.

다음 예제를 보자..


int main()
{
	char* name{};
    name = getname();	// 문자열의 주소를 name에 대입한다.
    cout << (int*) name << " : " << name << endl;
    delete []name;
    
    name = getname();	// 해제한 메모리를 다시 사용한다.
    cout << (int*)name << " : " << name << endl;
    delete []name;
    return 0;
}

char* getname()
{
	char temp[80]{};						// 임시배열
    cout << "이름을 입력하십시오 : ";
    cin >> temp;
    char* pn = new char[ strlen(temp) +1 ];	// 문자열을 더 작은 공간으로 복사
    strcpy(pn, temp);
    return pn;								// 함수가 종료될 때, temp는 소멸
}

프로그램 분석
getname()에선, cin을 통해 문자열을 입력 받아 임시 배열인 temp에 저장한다.

그 후, 정식으로 저장할 새로운 메모리 블록을 new를 사용하여 대입한다.

문자열을 저장하려면 널 문자까지 포함하여 strlen(temp)+1 바이트가 필요하다.

이 값이 new로 전달되어 적당한 크기의 새로운 메모리 블록이 확보되면,

temp에 들어 있는 문자열을 새로운 메모리 블록으로 복사한다.

getname() 함수는 메모리 블록의 크기가 적절한지 검사하지 않는다.

new를 통해 적당한 바이트 수를 대입한 것이므로, 아무런 문제가 없기 때문이다.

마지막으로, 이 함수는 복사된 문자열이 저장된 메모리 블록의 주소 pn을 리턴한다.

main()에선 리턴된 pn의 값(주소)를 name에 대입한다.

이 후, main()에선, getname()을 통해 대입 받은 주소와 문자열을 출력한다.

다음으로, main()은 name이 지시하던 메모리를 해제, getname()을 다시 호출한다.

이 예제에서는 getname()함수에서 대입한 메모리를 main()함수에서 해제한다.

이와 같이 new와 delete를 서로 다른 함수에서 사용하는 것은

가능하긴 하지만, 결코 좋은 생각은 아니다.

delete를 사용하는 일을 잊어버리기 쉽기 때문이다.


출처 : C++ 기초 플러스 6판 / 성안당


profile
Enthusiastic Game Developer

0개의 댓글