모두의 코드
C++ 레퍼런스 - std::array (안전한 배열)
std::array
<array>
에 정의 되어 있음 (C++ 11 에 추가됨)
template <class T, std::size_t N> struct array;
std::array 는 고정된 크기의 배열을 담고 있는 컨테이너 이다.
이 컨테이너는 마치 C 언어에서의 배열인 T[N]
과 비슷하게 작동하는데, 예를 들어서 C 배열 처럼 {}
를 통해 초기화 할 수 있습니다. (예컨대 std::array<int, 3> a = {1,2,3}
). 다만 한 가지 차이점은 C 배열과는 다르게 배열의 이름이 T*
로 자동 형변환 되지 않습니다.
std::array 를 통해서 기존의 C 배열과 같은 형태를 유지하면서 (오버헤드가 없습니다), C++ 에서 추가된 반복자라던지, 대입 연산자 등을 사용할 수 있습니다. (즉 <algorithm> 에 정의된 함수들을 std::array 에도 사용할 수 있다는 의미 입니다.)
참고로 크기가 0 인 std::array 의 경우 (즉 N
이 0 일 때), array.begin() == array.end()
이며, front()
나 back()
을 호출할 시 그 결과는 정의되지 않습니다 (Undefined behavior).
쉽게 생각해서 std::array 는 N
개의 같은 타입의 원소들을 담고 있는 tuple
이라 보시면 됩니다.
반복자 무효화
std::array 의 반복자는 배열 객체가 살아있는 동안 절대로 무효화 되지 않습니다. 다만 swap
후에, 기존의 반복자가 같은 위치를 계속 가리키고 있으므로 다른 값을 가리킬 수 도 있습니다.
생성자
std::array 는 Aggregate 타입 이기 때문에 aggregate 초기화 방식을 사용할 수 있습니다. 이 말은 즉슨, 아래와 같이 배열을 초기화 할 수 있다는 의미 입니다.
std::array<int, 3> arr = {1, 2, 3};
소멸자
배열 소멸 시에 모든 원소들의 소멸자를 호출합니다.
대입 연산자 (operator=)
배열의 각각의 원소들에 대해 대입 연산자를 호출합니다. 쉽게 말해
std::array<int, 3> a = {1, 2, 3}; std::array<int, 3> b; b = a; // b 에 {1,2,3} 이 들어간다
가 됩니다. 반면에 C 배열의 경우
int arr[3] = {1, 2, 3}; int b[3]; b = arr; // <-- 불가능!!
위와 같은 작업은 불가능 하고 memcpy 와 같은 함수를 통해 복사를 해줘야 합니다.
멤버 접근 함수
at, operator[]
두 함수 모두 인자로 전달한 위치에 있는 원소의 레퍼런스를 리턴합니다. 다만 at()
의 경우 인덱스의 위치를 체크해서 인덱스가 배열의 범위를 벗어난다면 예외를 throw
합니다.
#include <array> #include <iostream> int main() { std::array<int, 6> data = {1, 2, 4, 5, 5, 6}; // Set element 1 data.at(1) = 88; // Read element 2 std::cout << "인덱스 2 에 위치한 원소 : " << data.at(2) << '\n'; std::cout << "data 배열의 크기 = " << data.size() << '\n'; try { // Set element 6 data.at(6) = 666; } catch (std::out_of_range const& exc) { std::cout << "예외 발생 : " << exc.what() << '\n'; } // Print final values std::cout << "data:"; for (int elem : data) std::cout << " " << elem; std::cout << '\n'; }
성공적으로 컴파일 하였다면
실행 결과
인덱스 2 에 위치한 원소 : 4 data 배열의 크기 = 6 예외 발생 : array::at: __n (which is 6) >= _Nm (which is 6) data: 1 88 4 5 5 6
위와 같이 data.at(6)
처럼 배열의 크기를 벗어나는 원소를 참조할 경우 std::out_of_range
예외가 발생합니다.
반면에 operator[]
의 경우 C 의 배열 처럼 배열의 범위를 따로 체크하지 않습니다. 따라서 at
에 비해서 속도가 살짝 빠를 수 있지만, 범위 밖에 원소를 참조하는 일은 정의되지 않은 작업 입니다.
front, back
각각 첫 번째와 마지막 원소의 참조자를 리턴합니다. 만일 배열의 크기가 0 이라면, 해당 함수를 호출하는 작업은 정의되지 않은 작업 입니다.
data
std::array 가 참조하고 있는 배열의 시작 주소값을 리턴합니다.
#include <array> #include <cstddef> #include <iostream> void pointer_func(const int* p, std::size_t size) { std::cout << "data = "; for (std::size_t i = 0; i < size; ++i) std::cout << p[i] << ' '; std::cout << '\n'; } int main() { std::array<int, 4> container{1, 2, 3, 4}; pointer_func(container.data(), container.size()); }
성공적으로 컴파일 하였다면
실행 결과
data = 1 2 3 4
와 같이 나옵니다. 만일 비어 있지 않은 배열이라면 리턴한 포인터의 경우 첫 번째 원소의 주소값과 같습니다. 반면에 크기가 0 인 배열의 경우 data()
의 리턴값이 nullptr
일 수 도, 아닐 수 도 있습니다.
반복자들
begin, cbegin
시작점을 나타내는 반복자를 리턴합니다. 참고로 cbegin
의 경우 상수 반복자를 리턴. 보통 begin()
을 역참조 하게 되면 첫 번째 원소를 가리키게 됩니다.
end, cend
끝을 나타내는 반복자를 리턴합니다. 보통 end()
의 경우 맨 마지막 원소 바로 다음을 나타냅니다.
rbegin, crbegin
역참조 반복자의 시작점을 리턴합니다. 역참조시에 보통 맨 마지막 원소를 나타내게 됩니다.
rend, crend
역참조 반복자의 끝점을 리턴합니다.
#include <array> #include <iostream> int main() { std::array<int, 6> data = {1, 2, 4, 5, 5, 6}; std::cout << "정방향 반복자 : "; for (auto itr = data.cbegin(); itr != data.cend(); ++itr) { std::cout << *itr << " "; } std::cout << std::endl; std::cout << "역방향 반복자 : "; for (auto itr = data.crbegin(); itr != data.crend(); ++itr) { std::cout << *itr << " "; } std::cout << std::endl; }
성공적으로 컴파일 하였따면
실행 결과
정방향 반복자 : 1 2 4 5 5 6 역방향 반복자 : 6 5 5 4 2 1
와 같이 잘 나옵니다. 또한 반복자를 이용해서 algorithm 라이브러리의 여러 함수들을 모두 이용할 수 있습니다. 예를 들어서
#include <algorithm> #include <array> #include <iostream> int main() { std::array<int, 6> data = {3, 1, 5, 2, 6, 4}; std::sort(data.begin(), data.end()); // 마찬가지로 begin() 과 end() 가 지원되므로 range for 을 사용할 수 있습니다. for (int d : data) { std::cout << d << " "; } }
성공적으로 컴파일 했다면
실행 결과
1 2 3 4 5 6
와 같이 잘 정렬되서 나옵니다.
크기 관련
empty
크기가 0 인지 아닌지 확인 합니다.
std::array<int, 4> arr; arr.empty(); // false std::array<int, 0> brr; brr.empty(); // true
size
배열의 원소의 개수 (N) 를 리턴합니다.
max_size
배열의 최대 원소 개수를 리턴합니다. 사실 배열의 경우 size
와 max_size
둘 다 N
을 리턴합니다. 왜냐하면 배열의 크기는 바뀔 수 없기 때문이죠.
여러가지 작업 관련
fill
배열의 원소들을 인자로 전달된 값으로 채웁니다.
std::array<int, 5> arr; arr.fill(3); // arr 은 {3,3,3,3,3}
swap
두 배열의 내용을 바꿉니다.
참고 자료
<vector>
: std::array 와는 다르게 데이터 컨테이너의 크기를 줄이거나 늘릴 수 있습니다.

댓글을 불러오는 중입니다..