STL(Standard Template Library) 컨테이너(Container) - Vector
STL 컨테이너의 목적
모든 컨테이너에 적용되는 표준 인터페이스(iterator) -> 극단적인 OOP 는 문제가 될 수 있다.
std 알고리듬은 많은 컨테이너에서 작동
템플릿 프로그래밍 기반
메모리 자동 관리 -> 가장 주요한 특징, 하지만 메모리 파편화는 문제가 될 수 있다.
STL 컨테이너 문제점
아래와 같은 STL 의 문제점으로 회사 내부에서 STL 대체품들을 만들기도 한다.
-> EA, Epic Games ..
문제점1. 모든 컨테이너에 알맞은 표준 인터페이라는 환상..!
모든 컨테이너에 같은 인터페이스가 적용되는 것은 이상하다. -> 극단적으로 OOP 를 추구한 사례 -> 모든 컨테이너가 동작하는 방법이 약간은 다른데, 이것을 메서드 명으로 파악하기가 어렵다..
문제점2. 메모리 단편화
빈번한 메모리 재할당은 메모리 단편화를 초래함
메모리 단편화는 엄청난 문제가 될 수 있다! -> 특히 가상 메모리를 지원하지 않는 플랫폼에서 프로그램을 실행할 때!
메모리 단편화 때문에, 애플리케이션은 뻗어 버릴 수 있다. -> 즉, 총 여유 공간은 충분하나 충분히 큰 연속되는 메모리가 없는 경우!
디버깅 및 고치는게 쉽지 않음 ..
Vector
어떤 자료형도 넣을 수 있는 동적 배열 (자동으로 늘려준다, string 같이)
그 안에 저장된 모든 요소들이 연속적인 메모리 공간에 위치 -> Vector 는 메모리를 자동적으로 관리해주는 배열로 정리할 수 있다!
배열이기 때문에, 인덱스만 알고 있다면 어떤 요소에도 임의로 접근할 수 있다.
Vector 만들기
reserve() 함수 사용 시, 용량이 증가해야 한다면 새로운 저장 공간을 재할당하고 기존 요소들을 모두 새 공간으로 복사한다. -> 예를 들어서 사용해야할 공간이 500byte 라면 미리 공간을 할당하면 string 에 비해서 메모리를 재할당하는 횟수가 적어진다. -> 해당 과정을 컴파일러가 최적화해준다. (vector 생성 후 바로 500byte 를 할당한다면 처음부터 500byte 를 할당해준다)
동일한 크기과 데이터를 같는 vector 를 생성할 수 있다. -> 복사 생성자와 동작하는 방식이 비슷하다.
Vector 요소에 접근하기
순차적으로 요소에 접근하게
반복문을 통해서, 요소에 접근하는 것은 벡터에서만 사용할 수 있다..
맵(map) 에서는 반복문을 사용할 수 없다.
때문에, STL 컨테이너를 순회할 때는 반복자(iterator) 를 사용하는 것이 표준방식이다.
반복자(iterator) 와 포인터의 차이점
포인터는 직접적으로 메모리 주소를 다루고 접근하는 데 사용되는 반면,
Iterator는 데이터 구조를 추상화하고 보다 일반적인 방식으로 순회하고 접근하는 데 사용됩니다. -> 포인터보다 Iterator가 더 추상화된 수준의 개념이며, (극단적인 OOP 의 단점도 존재한다) -> 이는 보다 유연하고 안전한 코드 작성을 가능하게 합니다.
뒤에서부터 Vector 요소에 접근하기
begin(), end() 가 아닌 rbegin(), rend() 를 사용하면 된다.
Vector 요소의 삽입과 삭제
특정 위치에 요소 삽입하기
특정 위치에 요소 삭제하기
하지만 Vector 는 메모리 복사 && 재할당 문제가 발생한다.(배열의 고질적인 문제)
메모리 복사 : 삽입되는 인덱스 뒤에 데이터는 모두 복사 되어야 한다.
메모리 재할당 : 할당된 메모리보다 데이터를 더 집어넣을 때 메모리를 재할당 받고 기존 데이터를 옮긴다.
Vector 요소 교환하기
swap 함수는 각각의 vector 의 주소만 변경하면 되기 때문에, 무거운 연산은 아니다!
개체(object) 백터
이전에 c++ 은 개체 배열 생성 시 각 요소 마다 주소값이 아닌 개체 멤버변수를 저장한다고 했다.
백터 또한 내부적으로는 배열로 구현되어 있기 때문에, 요소마다 주소값이 아닌 멤버변수를 저장한다.
개체(object) 포인터 백터
백터에 개체를 직접 저장 시 다음과 같이 2가지 문제가 발생한다. -> 개체 배열은 값을 직접 저장한다는 특정 때문이다.
사이즈 보다 개체를 많이 저장해야 할 시 기존 데이터를 모두 복사해야 한다. (개체의 일반적으로 사이즈는 크다..)
백터의 사본을 만들 때 기존에 데이터를 모두 복사해야 한다. (개체의 일반적으로 사이즈는 크다..)
때문에, 개체의 크기가 크다면 포인터를 저장해야 한다. (Java 의 방식!)
개체 포인터 백터를 모두 사용했다면, delete 를 호출해서 메모리를 반납해주어야 한다!
Last updated