Array 클래스: 고정 크기의 동적 배열#pragma once
#include <assert.h>
class Array {
using T = int;
#pragma once: 헤더 파일의 중복 포함을 방지합니다.#include <assert.h>: assert는 디버깅 중 조건이 참인지 확인하는 매크로입니다. 조건이 거짓일 경우 프로그램을 중단시킵니다.using T = int: 타입 별칭으로 T를 정의하여, 나중에 변경이 쉽도록 합니다. 이 클래스는 정수형 배열(int)을 다룹니다.public:
explicit Array(int capacity = 100) : _capacity(capacity) {
_buffer = new T[capacity];
}
~Array() {
delete[] _buffer;
}
explicit Array(int capacity = 100):
_buffer = new T[capacity]: 배열을 동적으로 생성합니다.~Array():
delete[] _buffer: 배열을 삭제합니다. 메모리 누수를 방지하기 위해 반드시 호출됩니다.push_backvoid push_back(const T& data) {
if (_size == _capacity) {
return; // 용량 초과 시 데이터를 추가하지 않음
}
_buffer[_size] = data; // 배열 끝에 데이터 추가
_size++; // 크기 증가
}
_size == _capacity를 확인하여 용량 초과 여부를 판단합니다._buffer[_size] = data: 배열 끝에 데이터를 저장합니다._size++: 배열 크기를 증가시킵니다.operator[]T& operator[](int index) {
assert(index >= 0 && index < _size); // 인덱스 범위 검사
return _buffer[index];
}
assert(index >= 0 && index < _size): 유효한 인덱스인지 확인합니다. 유효하지 않으면 프로그램을 중단합니다.return _buffer[index]: 인덱스에 해당하는 데이터를 반환합니다.int size() { return _size; }
int capacity() { return _capacity; }
size(): 현재 저장된 데이터의 개수를 반환합니다.capacity(): 배열의 용량을 반환합니다.private:
T* _buffer = nullptr; // 데이터 저장 공간
int _size = 0; // 현재 크기
int _capacity = 0; // 최대 용량
};
_buffer: 동적으로 할당된 배열을 가리키는 포인터._size: 현재 저장된 요소의 개수._capacity: 배열의 최대 크기.Array 클래스의 사용 예제Array arr(100);
arr.push_back(1);
arr.push_back(2);
arr.push_back(3);
arr[1] = 10; // 배열 요소 수정
int val = arr[1000]; // 잘못된 접근 (assert로 오류 발생)
Vector 클래스: 크기 조정이 가능한 동적 배열#pragma once
#include <assert.h>
template<typename T>
class Vector {
public:
explicit Vector() {}
~Vector() {
if (_buffer) {
delete[] _buffer;
}
}
템플릿 클래스:
template<typename T>: 데이터 타입에 대해 일반화된 구현을 제공합니다.Vector<int>, Vector<float>, Vector<std::string> 등.생성자와 소멸자:
Vector()는 초기화를 수행하지 않습니다.~Vector()는 _buffer가 할당되었는지 확인 후 해제합니다.push_backvoid push_back(const T& data) {
if (_size == _capacity) {
int newCapacity = static_cast<int>(_capacity * 1.5);
if (newCapacity == _capacity) {
newCapacity++;
}
reserve(newCapacity);
}
_buffer[_size] = data;
_size++;
}
용량 검사 및 확장:
_size == _capacity일 경우 reserve를 호출하여 배열의 용량을 늘립니다.1.5배로 설정되며, 최소 1씩 증가합니다.데이터 추가:
_buffer[_size] = data: 배열의 마지막에 데이터를 저장합니다._size++: 크기를 증가시킵니다.reservevoid reserve(int capacity) {
if (_capacity >= capacity) {
return;
}
_capacity = capacity;
T* newData = new T[_capacity];
for (int i = 0; i < _size; i++) {
newData[i] = _buffer[i];
}
if (_buffer) {
delete[] _buffer;
}
_buffer = newData;
}
확장 필요 확인:
_capacity >= capacity: 이미 충분한 용량이 있으면 반환합니다.새 버퍼 생성 및 데이터 복사:
newData = new T[_capacity]: 새 용량으로 배열을 생성합니다.newData[i] = _buffer[i]: 기존 데이터를 새 배열로 복사합니다.기존 버퍼 해제:
delete[] _buffer: 기존 배열을 삭제합니다.새 버퍼로 교체:
_buffer = newData: 새 배열을 현재 버퍼로 설정합니다.void pop_back() {
_size--;
}
T& back() {
return _buffer[_size - 1];
}
void clear() {
if (_buffer) {
delete[] _buffer;
_buffer = new T[_capacity];
}
_size = 0;
}
pop_back: 배열의 마지막 요소를 제거합니다.back: 마지막 요소를 반환합니다.clear: 배열의 모든 데이터를 초기화합니다. 용량은 유지됩니다.Vector 클래스의 사용 예제Vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v[1] = 10; // 배열 요소 수정
v.pop_back(); // 마지막 요소 제거
v.clear(); // 배열 초기화
resize와 reserve의 차이resize:
reserve:
장점:
std::vector처럼 동작하며, 다양한 데이터 타입에 적용 가능합니다.단점:
사용 사례: