[C++] std::array

Artiper
|2025. 5. 3. 14:09

std::array

C++ 11에 추가된 std::array는 <array>에 정의되어 있다. C 스타일의 배열과 다른 점은 배열의 이름이 `T*`로  자동 형변환 되지 않는다. C 스타일의 배열을 사용하게 되면 함수 매개변수에 집어넣었을 때, 포인터로 강제 변환되어 배열의 크기가 날라가는 불편한 점도 초래한다. 배열 크기가 소멸되는 이유는 `int arr[]`처럼 함수의 매개변수를 설정하더라도, 함수 내부에서 `int* arr`와 동일하게 해석한다. (sizeof() 연산하면, 그냥 포인터 크기만 계산됨.) 이 떄문에 배열의 크기를 같이 함수 매개변수에 넘겨주어야 하는 과정이 생긴다.

 

또한 반복자(iterator), 대입 연산자 등을 사용할 수 있다. 이 덕분에 <algorithm>에 정의된 함수를 std::array에 사용할 수 있는데, 예를 들어 sort와 같은 함수도 다음과 같은 형태로 사용할 수 있다.

std::array<int, 5> a;
std::sort(a.begin(), a.end());

 

생성자

std::array는 aggregate 타입으로, aggregate initilization이 가능하다. (struct 변수를 초기화 할 때 중괄호를 통해 초기화를 하는 것처럼.)

#include <array>

std::array<int, 5> a = {1, 2, 3, 4, 5};

 

대입 연산자

std::array를 사용할 경우 배열간 대입 연산이 가능해진다.

std::array<int, 5> a1 = {1, 2, 3, 4, 5};
std::array<int, 5> a2;

a2 = a1;
for (auto val : a2) {
    std::cout << "val: " << val << '\n';
}

/*
val: 1
val: 2
val: 3
val: 4
val: 5
*/

 

하지만 C 스타일의 배열 같은 경우는 "Array type int[3] is not assignable"과 같은 에러를 보여준다.

int arr[3] = {1, 2, 3};
int b[3];

b = arr; // 에러 발생

원하는 연산을 수행하려면 memcpy 함수를 통해 복사를 해주어야 한다.

 

멤버 접근 함수

at, operator[]

위 두 함수 모두 인자로 전달한 위치에 있는 원소의 레퍼런스를 반환한다. `at()`의 경우 인덱스의 위치를 체크해서 인덱스가 배열의 범위를 벗어나면 예외를 throw한다.

 

정상 작동

std::array<int, 3> arr = {1, 2, 3};
std::cout << arr.at(1);
// 출력: 2

 

예외 처리

std::array<int, 3> arr = {1, 2, 3};
std::cout << arr.at(3);

/* 출력
terminate called after throwing an instance of 'std::out_of_range'
  what():  array::at: __n (which is 3) >= _Nm (which is 3)
*/

std::out_of_range 익셉션을 반환하는 것을 확인 가능하다. 

 

opertor[]는 .at()과 달리 C스타일 배열처 범위를 따로 체크하지 않는다.

std::array<int, 3> arr = {1, 2, 3};
std::cout << arr[2];
// 출력: 3

std::array<int, 3> arr = {1, 2, 3};
std::cout << arr[3];
// 출력: -977053312

 

 

함수에 대한 값의 복사와 전달

std::array는 매개변수로 전달될 때 값 복사가 된다. return을 할 때도 포인터가 아닌 값을 그대로 반환할 수 있다.

 

만약, 참조로 전달하고 싶다면 다음과 같이 매개변수를 선언한다.

void foo(std::array<int, 5>& arr);

 

그리고 여기서 값의 수정이 발생하지 않도록 한다면,

void foo(const std::array<int, 5>& arr);

이와 같이 선언하면 된다.

 

C 스타일과 비교한 std::array의 장점 요약

  1. STL 스타일의 반복자 기반 알고리즘과 함께 사용가능 하다.
  2. C 스타일의 배열과 다르게 함수 매개변수에 값으로 전달하거나, 반환할 수 있다.
  3. at()을 사용하여 예외처리가 가능하다.
  4. C 스타일의 배열과 성능은 완전 동일하다.

 

C 코드의 확장성을 염두에 둔 것이 아니라면, 얌전히 std::array를 사용해야 겠다.

 

참고 자료