동적으로 배열 할당하기 (Dynamically allocating arrays)
단일 변수에 대한 동적 할당뿐만 아니라 배열 변수를 동적 할당할 수 있다. 컴파일 타임에 배열 길이를 정하는 고정 배열(fixed array)과 다르게 배열을 동적으로 할당하면 런타임 동안에 배열 길이를 선택할 수 있다.
동적으로 배열을 할당하려면, new[]
연산자와 delete[]
연산자를 사용해야 한다.
#include <iostream>
int main()
{
std::cout << "Enter a positive integer: ";
int length;
std::cin >> length;
int *array = new int[length]; // 배열 버전 new 연산자를 사용한다. 배열 길이는 상수가 아니여도 된다.
std::cout << "I just allocated an array of integers of length " << length << '\n';
array[0] = 5; // 요소 0을 값 5로 설정
delete[] array; // 배열 할당 해제를 위해 배열 버전 delete 연산자를 사용한다.
return 0;
}
배열을 할당하기 때문에 new[]
와 같은 배열 버전 new 연산자를 사용해야 한다.
이 메모리는 고정 배열(fixed array)에 사용되는 메모리와 다른 위치에서 할당되므로 배열의 크기가 상당히 클 수 있다. 위의 프로그램을 실행하고 100만 개 크기의 배열을 할당해도 문제없이 할당할 수 있다. 이 때문에 C++에서 많은 메모리를 할당해야 하는 프로그램은 동적으로 메모리를 할당하는 게 일반적이다.
동적으로 배열 해제하기 (Dynamically deleting arrays)
동적으로 할당된 배열을 해제하려면, delete[] 연산자를 사용하면 된다.
이것은 단일 변수 대신 여러 변수를 정리해야 한다는 것을 CPU에 알려준다. 동적 할당에서 프로그래머가 자주 하는 실수 중 하나는 동적으로 할당된 배열을 해제할 때 delete[]
대신 delete
를 사용하는 것이다. 배열에서 delete의 스칼라 버전을 사용하면 데이터 손상, 메모리 누수, 충돌 또는 기타 문제와 같은 정의되지 않은 동작이 발생한다.
배열 해제 시 어떻게 해제할 메모리양을 알 수 있을까? 답은 new[]
가 변수에 할당된 메모리양을 추적하므로 delete[]
는 적절한 메모리를 해제할 수 있다. 불행하게도 프로그래머는 이 크기∙길이에 접근할 수 없다.
Dynamic arrays are almost identical to fixed arrays
'07.09 - 포인터와 배열' 포스트에서 '고정 배열 변수는 마치 포인터인 것처럼 배열의 첫 번째 요소의 주소를 가지고 있다'고 배웠다. 또한 '고정 배열은 배열의 첫 번째 요소를 가리키는 포인터로 변환될 수 있다'는 사실도 배웠다. 변환된 형태에서는 sizeof()
을 통해 배열의 길이를 알 수 없다.
동적 배열은 배열의 첫번째 요소를 가리키는 포인터다. 이것은 고정 배열이 포인터로 변환된 형태와 동일하게 작동하지만, delete []
를 통해 동적 배열을 할당 해제해야 한다.
동적 배열 초기화 (Initializing dynamically allocated arrays)
동적 배열을 0으로 초기화하는 문법은 매우 간단하다.
int* array = new int[length]();
C++ 11 이전에는 동적 배열을 0이 아닌 값으로 초기화하는 간단한 방법이 없었기 때문에 반복해서 요소 값을 명시적으로 지정해야 했다.
int* array = new int[5];
array[0] = 9;
array[1] = 7;
array[2] = 5;
array[3] = 3;
array[4] = 1;
하지만 C++ 11부터 초기화 리스트(initializer list)를 사용해 동적 배열을 초기화할 수 있다!
int fixedArray[5] = { 9, 7, 5, 3, 1 }; // initialize a fixed array in C++03
int* array = new int[5] { 9, 7, 5, 3, 1 }; // initialize a dynamic array in C++11
일관성을 위해 C++ 11에서는 유니온 초기화를 사용하여 고정 배열도 초기화할 수 있다.
int fixedArray[5] { 9, 7, 5, 3, 1 }; // initialize a fixed array in C++11
char fixedArray[14] { "Hello, world!" }; // initialize a fixed array in C++11
주의사항: 동적 배열을 C 스타일 문자열로 초기화할 수 없다.
char* array = new char[14] { "Hello, world!" }; // doesn't work in C++11
이렇게 해야 하는 경우 다음과 같이 해야 한다.
또한, 동적 배열은 명시적으로 길이를 설정해 선언해야 한다.
int fixedArray[] {1, 2, 3}; // okay: implicit array size for fixed arrays
int* dynamicArray1 = new int[] {1, 2, 3}; // not okay: implicit size for dynamic arrays
int* dynamicArray2 = new int[3] {1, 2, 3}; // okay: explicit size for dynamic arrays
번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/6-9a-dynamically-allocating-arrays/ 입니다.
2018/07/25 - [C++ 이야기/07. 배열, 문자열, 포인터 및 레퍼런스] - C++ 07.12 - new와 delete를 사용한 동적 메모리 할당 (Dynamic memory allocation with new and delete)