5. 새로운 배열 - std::array

크기를 미리 지정할 수 있다면 배열을 사용하고, 미리 크기를 지정할 수 없는 경우 동적으로 크기가 증가하는 STL 컨테이너를 사용하면 됩니다.

벡터의 특징

  1. 생성과 소멸에 드는 비용이 만만치 않습니다. 이 오버헤드는 특히 사용해야 하는 벡터의 수가 많으면 많을수록 증가한다.
  2. 일단 벡터 객체 하나를 생성한 후, 내부에 새로운 요소를 할당append할 때, 이 동작은 런타임에 실행된다. 벡터는 크기가 정해지지 않은 동적 배열이므로 이 역시 성능에 예민한 애플리케이션에는 좋지 않다.
  3. 벡터 객체는 대부분 32바이트를 차지하므로 메모리를 비효율적으로 사용할 수 있다.
  4. 동적으로 증가하거나 감소하는 경우 불필요한 벡터 간 복사가 일어난다(사실 이 부분은 C++11에서 이동 시맨틱move semantics이라는 개념에 의해 극복).

std::array의 장점
벡터와 같이 정해진 시간에 임의 접근이 가능하며, 메모리의 스택에 연속적으로 요소들을 배치할 수 있다. 보통 벡터는 자유 공간에 요소들을 비연속적으로 배치하여 사용합니다. 그런데 std::array는 요소들이 메모리 안 특정 지역에 모여있도록 배치하므로, CPU에서 해당 요소들을 좀 더 빠르게 처리할 수 있다
또한 std::array는 생성자, 소멸자, 복사 생성자, 대입 연산자를 지원하므로, 좀 더 C++다운 배열이라고 할 수 있다.

#include <array>
int main(int argc, char** argv) {
    std::array<int, 5> arr = {1, 2, 3};
    return 0;
}

초기화 리스트가 배열의 크기보다 작으면 0으로 자동 초기화 된다.

  • 포인터 타입 반환
int* p = arr; // 에러

int* p2 = arr.data(); // ok
const int* p3 = arr.data(); // ok
  • 배열의 크기 : 멤버함수 size()를 통해 알아낼 수 있음.
std::cout<<arr.size()<<std::endl; // 출력 값 5
  • 부모 타입으로 타입 변환 금지
class Dog: Animal { }
class Elephant : Animal { }
    void foo(std::array<Animal*, 5>& arr) {
    arr[3] = new Elephant;
}

int main(int argc, char** argv) {
    std::array<Dog*, 5> dogs;
    foo(dogs); // 에러!!!
    return 0;
}

벡터의 경우와는 다르게 std::array는 묵시적인 객체 타입의 타입 변환인 ‘Derived-to-Base’ 변환을 금지합니다. 가령 위의 코드는 에러가 발생.

  • 제공되는 인터페이스

아래의 코드는 모두 유효함.

#include <iostream>
#include <array>
//...
std::array<int, 5> arr = {1, 2, 3};

//...
auto it = arr.begin();

// 위 코드는 std::array<int. 5>::iterator it = arr.begin()과 같음
while(it != arr.end()) {
    std::cout<<*it<<std::endl;
    it++;
}

// ...
std::array<int, 5>::size_type size = arr.size();

arr.fill(12); // 모든 배열 원소의 값을 12로 할당

bool isEmpty = arr.empty();

// 벡터에서 지원되는 멤버 함수(operator[ ], at, front, back)도 지원합니다.

std::array와 std::vector의 비교

  • std::array는 크기가 고정되어 있으며 std::vector는 동적으로 증가.
  • std::array는 동적 메모리를 사용하지 않지만 std::vector는 동적 메모리를 사용.

std::array와 C-Array의 비교

  • std::array는 객체이므로 크기를 알 수 있지만 C-Array는 크기를 알 수 없다.
  • std::array는 요소가 하나도 없어도 되지만 C-Array는 하나 이상 있어야 한다.
  • std::array는 생성시 파라미터를 통해 명시적으로 크기를 알려줘야 하지만, C-Array는 초기화를 통해 크기를 추측해낼 수 있다.
  • std::array는 대입이 가능하지만 C-Array는 불가능하다.