동적 메모리 할당
동적 메모리 할당 개요
동적 메모리 할당은 프로그램 실행 중에 메모리를 할당하고 해제하는 기능입니다.
이를 통해 프로그램은 실행 시간에 필요한 만큼의 메모리를 사용할 수 있어, 메모리 사용의 유연성과 효율성을 높일 수 있습니다.
new 연산자
new
연산자는 동적으로 메모리를 할당하고, 할당된 메모리의 주소를 반환합니다.
#include <iostream>
int main() {
// 단일 정수 할당
int* ptr = new int;
*ptr = 10;
std::cout << "값: " << *ptr << std::endl;
// 초기화와 함께 할당
int* ptr2 = new int(20);
std::cout << "초기화된 값: " << *ptr2 << std::endl;
// 메모리 해제
delete ptr;
delete ptr2;
return 0;
}
delete 연산자
delete
연산자는 동적으로 할당된 메모리를 해제합니다.
int* ptr = new int;
delete ptr; // 메모리 해제
ptr = nullptr; // 포인터를 널로 설정 (좋은 습관)
동적 배열 할당
new[]
를 사용하여 배열을 동적으로 할당할 수 있습니다.
#include <iostream>
int main() {
int size;
std::cout << "배열 크기 입력: ";
std::cin >> size;
int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = i * 10;
}
for (int i = 0; i < size; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
delete[] arr; // 배열 메모리 해제
return 0;
}
2차원 배열의 동적 할당
2차원 배열을 동적으로 할당하는 방법은 다음과 같습니다.
#include <iostream>
int main() {
int rows = 3, cols = 4;
// 2차원 배열 할당
int** matrix = new int*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new int[cols];
}
// 배열 사용
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = i * cols + j;
std::cout << matrix[i][j] << " ";
}
std::cout << std::endl;
}
// 메모리 해제
for (int i = 0; i < rows; i++) {
delete[] matrix[i];
}
delete[] matrix;
return 0;
}
메모리 누수 (Memory Leak)
메모리 누수는 할당된 메모리를 해제하지 않을 때 발생합니다.
이는 프로그램의 성능 저하와 crash를 유발할 수 있습니다.
void memoryLeakExample() {
int* ptr = new int;
// delete ptr; // 이 줄이 없으면 메모리 누수 발생
}
int main() {
for (int i = 0; i < 1000000; i++) {
memoryLeakExample(); // 메모리 누수 누적
}
return 0;
}
예외 처리와 메모리 할당
메모리 할당 실패 시 예외 처리를 통해 안전하게 프로그램을 관리할 수 있습니다.
#include <iostream>
#include <new>
int main() {
try {
int* largeArray = new int[1000000000]; // 매우 큰 배열 할당 시도
delete[] largeArray;
} catch (const std::bad_alloc& e) {
std::cout << "메모리 할당 실패: " << e.what() << std::endl;
}
return 0;
}
스마트 포인터 소개
C++ 11부터 도입된 스마트 포인터는 메모리 관리를 자동화하여 메모리 누수를 방지합니다.
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "생성됨" << std::endl; }
~MyClass() { std::cout << "소멸됨" << std::endl; }
};
int main() {
{
std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
// ptr은 블록이 끝날 때 자동으로 해제됩니다.
}
std::cout << "블록 끝" << std::endl;
return 0;
}
RAII
RAII (Resource Acquisition Is Initialization)는 자원의 수명을 객체의 수명과 연결하여 자동으로 관리하는 C++ 프로그래밍 기법입니다.
#include <iostream>
class RAIIExample {
private:
int* data;
public:
RAIIExample(int size) : data(new int[size]) {
std::cout << "자원 할당" << std::endl;
}
~RAIIExample() {
delete[] data;
std::cout << "자원 해제" << std::endl;
}
};
int main() {
{
RAIIExample example(10);
// 객체가 소멸될 때 자원이 자동으로 해제됩니다.
}
std::cout << "프로그램 종료" << std::endl;
return 0;
}
연습 문제
- 동적으로 할당된 정수 배열에 사용자로부터 값을 입력받고, 이를 정렬한 후 출력하는 프로그램을 작성하세요.
- 학생 정보(이름, 나이, 성적)를 저장하는 클래스를 만들고, 여러 학생 객체를 동적으로 생성하여 관리하는 프로그램을 구현하세요.
- 2차원 동적 배열을 사용하여 행렬 곱셈을 수행하는 프로그램을 작성하세요.
참고자료
- C++ 공식 문서의 동적 메모리 관리 섹션 : Dynamic memory management
- "Effective C++" by Scott Meyers (항목 16 : new와 delete를 사용할 때는 형태를 반드시 맞추자)
- "C++ Primer" by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo (Chapter 12 : Dynamic Memory)
- C++ Core Guidelines의 자원 관리 관련 규칙 : R : Resource management
- "Modern C++ Programming with Test-Driven Development" by Jeff Langr (Chapter 7 : Memory Management)