1. 동적 할당
필요성
동적 할당은 프로그램 실행 중 메모리를 동적으로 할당하고 해제하는데 사용됩니다.
정적 할당은 컴파일 시점에 크기를 결정하고, 프로그램이 실행되는 동안 크기를 변경하기 어렵습니다.
동적 할당은 다음과 같은 이유로 인해 사용됩니다.
- 유연한 크기의 자료구조 필요성
- 프로그램 실행 중에 데이터 크기가 동적으로 변할 때 동적 할당은 필수적입니다.
- 자원 효율
- 정확한 메모리 양을 미리 예측하기 어려운 경우, 동적 할당은 자원을 효율적으로 사용할 수 있게 해줍니다.
- 정확한 메모리 양을 미리 예측하기 어려운 경우, 동적 할당은 자원을 효율적으로 사용할 수 있게 해줍니다.
메모리 영역
- 동적 할당의 경우 메모리 영역에서 Heap 영역에 할당됩니다.
- 프로그램 실행 중 메모리를 동적으로 할당하고 해제하는데 사용되는 영역입니다.
종류
C++에서 동적 할당은 new와 delete 키워드를 사용하는 방식, 스마트 포인터를 사용하는 방식으로 나뉩니다. C Style에서는 malloc 을 이용하기도 합니다.
malloc 할당
int main()
{
// 할당
int* pInt = (int*)malloc(100);
// 해제
free(pInt);
}
malloc은 void* 반환형을 가지고 있습니다.
용량을 정의하면 그에 해당하는 용량을 가지고 있는 주소만을 제공합니다.
즉 해당 공간을 어떻게 사용할지는 사용자가 타입 변환(캐스팅)을 통해 정의해주어야 합니다.
new
와 delete
를 사용한 동적 할당
#include <iostream>
int main() {
// int 형 동적 할당
int *intPtr = new int;
*intPtr = 42;
std::cout << "Value: " << *intPtr << std::endl;
// 배열 동적 할당
char *charPtr = new char[*intPtr];
// 동적으로 할당된 메모리 해제
delete intPtr;
delete[] charPtr;
return 0;
}
c++ 에서 추가된 new 기능을 이용하면
동적 할당시에 타입을 지정해줄 수 있습니다.
delete의 경우 동적으로 할당된 메모리를 해제할 수 있습니다.
스마트 포인터를 사용한 동적 할당
#include <iostream>
#include <memory>
int main() {
// int 형 동적 할당 (std::unique_ptr 사용)
std::unique_ptr<int> intPtr = std::make_unique<int>(42);
std::cout << "Value: " << *intPtr << std::endl;
// 메모리는 스마트 포인터가 자동으로 해제
return 0;
}
다음과 같이 스마트 포인터를 이용하여 동적할당을 수행할 수도 있습니다.
2. 가변 배열
배열의 경우 크기를 중간에 변경하는 것이 불가능합니다.
그러나 프로그램을 수행하다 보면 배열에 담아야 할 데이터가 고정적이지 않고 유동적입니다.
이런 특성을 고려하여 c++에는 가변 배열을 생성할 필요성이 있습니다.
직접 구현
// .h, .hpp
class dynamicArray
{
private:
int* m_array;
int m_size;
int m_used;
public:
dynamicArray();
dynamicArray(int size);
~dynamicArray();
void popBack();
void pushBack(int data);
void print();
int &operator[](int index);
}
// dynamicArray.cc
dynamicArray::dynamicArray() : m_size(10), m_used(0)
{
m_array = new int[m_size];
}
dynamicArray::dynamicArray(int size) : m_size(size), m_used(0)
{
m_array = new int[m_size];
}
dynamicArray::~dynamicArray()
{
delete[] m_array;
}
void dynamicArray::popBack()
{
if(m_used == 0)
{
std::cout << "array is Empty" << std::endl;
return;
}
m_used--;
int* temp = new int[m_used];
for (int i = 0; i < m_used; ++i)
{
temp[i] = m_array[i];
}
delete[] m_array;
m_array = new int[m_size];
for (int i = 0; i < m_used; i++)
temp[i] = m_array[i];
delete[] temp;
return;
}
void dynamicArray::push_back(int data)
{
if(this->m_size > this->m_used)
{
this->m_array[this->m_used] = data;
}
else
{
int* temp = new int[this->m_size];
for (int i = 0; i < m_used; ++i)
{
temp[i] = this->m_array[i];
}
delete[] this->m_array;
this->m_array = new int[m_size * 2];
for (int i = 0; i < m_used; ++i)
{
m_array[i] = temp[i];
}
m_array[m_used] = data;
delete[] this->temp;
}
this->m_used++;
}
int& dynamicArray::operator[](int index){
return this->m_array[index];
}
가변 배열의 경우 꼭 필요한 크기 만큼 크기를 지정하거나, 필요한 크기보다 조금 더 크게 지정 하는 것이 메모리 자원을 아낄 수 있습니다.
std::vector
c++ 에서는 가변배열로 std::vector를 지원합니다.
std::vector는 배열크기를 가변적으로 사용할 수 있는 컨테이너 입니다.
문제 풀이
문제 1.
정수 배열을 동적으로 할당하고 사용자로부터 배열의 크기를 입력 받아 값을 저장하고 출력하는 프로그램을 작성하세요. 그 후, 동적으로 할당한 메모리를 반드시 해제하세요.
문제 2.
두 개의 정수를 동적으로 할당하고 사용자로부터 값을 입력 받아 두 값을 더한 결과를 출력하는 프로그램을 작성하세요. 그 후, 동적으로 할당한 메모리를 반드시 해제하세요.
문제 3.
std::vector를 사용하여 동적으로 크기가 변하는 정수 배열을 구현하세요. 배열에 값을 추가하고 제거하는 예제를 작성하세요.
'C++' 카테고리의 다른 글
C++ 자료구조 구현 Red-Black Tree (0) | 2024.11.30 |
---|---|
C++ 클래스 (0) | 2024.05.12 |
C++ 컴파일 과정 (0) | 2024.04.21 |
C++ Const 정확도(Const Correctness) (0) | 2024.04.06 |
C++ 연산자 (0) | 2024.02.28 |