배열 : C-style array vs std::array
개요
C++는 C 언어에서 파생되었기 때문에 C-style 배열을 지원합니다. 하지만 C-style 배열은 포인터로의 암시적 변환(decay) 특성 때문에 크기 정보를 잃어버리기 쉽고, 경계 검사를 지원하지 않아 메모리 관련 버그를 유발할 수 있습니다. C++11부터 도입된 std::array
는 이러한 단점을 보완한 현대적인 C++의 고정 크기 배열 컨테이너입니다. 이 문서에서는 두 배열 타입의 차이점과 std::array
의 장점을 설명합니다.
C++ 버전별 주요 키워드 도입 시기
- C++98/03: C-style 배열 사용.
- C++11:
std::array
도입.
내용 설명
C-style array
- 특징:
- 컴파일 시간에 크기가 결정되는 고정 크기 배열입니다.
- 메모리상에 연속적으로 할당됩니다.
- 함수에 인자로 전달될 때 배열의 이름은 배열의 첫 번째 요소를 가리키는 포인터로 변환(decay)됩니다. 이 과정에서 배열의 크기 정보가 사라집니다.
- 크기 정보를 잃어버리기 때문에, 배열과 함께 배열의 길이를 별도의 인자로 전달해야 합니다.
- 경계 검사(bounds checking)를 제공하지 않아, 인덱스를 벗어난 접근 시 정의되지 않은 동작(undefined behavior)을 유발할 수 있습니다.
std::array
- 특징:
- C-style 배열을 감싼 템플릿 클래스 컨테이너입니다. (
<array>
헤더 필요) - 배열의 크기가 타입의 일부로 명시되므로 (
std::array<T, N>
), 크기 정보를 항상 유지합니다. .size()
멤버 함수를 통해 언제든지 배열의 크기를 알 수 있습니다.- 함수에 전달할 때 포인터로 변환되지 않으며, 값이나 참조로 전체 객체를 전달할 수 있습니다.
[]
연산자는 경계 검사를 수행하지 않지만,.at()
멤버 함수는 경계 검사를 수행하고 범위를 벗어나면std::out_of_range
예외를 던집니다.- 반복자(iterator)를 지원하여 표준 라이브러리 알고리즘과 함께 사용하기 용이합니다.
- C-style 배열을 감싼 템플릿 클래스 컨테이너입니다. (
예제 코드
#include <array>
#include <cstdint>
#include <iostream>
// C-style array: 포인터로 디케이
void print_array_values1(const std::uint32_t *my_array, const std::uint32_t len)
{
std::cout << "--- C-style array ---" << std::endl;
for (std::uint32_t i = 0; i < len; i++)
{
std::cout << my_array[i] << "\n";
}
}
// C++ style array: std::array
template <std::size_t N>
void print_array_values2(const std::array<std::uint32_t, N>& my_array) // 참조로 받는 것이 효율적
{
std::cout << "--- std::array ---" << std::endl;
for (std::size_t i = 0; i < my_array.size(); i++)
{
std::cout << my_array[i] << "\n";
}
}
int main()
{
constexpr auto len = 5U;
// C-style array
std::uint32_t my_array[len] = {1, 2, 3, 4, 5};
print_array_values1(my_array, len);
// std::array
auto my_array2 = std::array<std::uint32_t, len>{6, 7, 8, 9, 10};
print_array_values2(my_array2);
return 0;
}
실행 결과
--- C-style array ---
1
2
3
4
5
--- std::array ---
6
7
8
9
10
활용팁
std::array
를 우선 사용하세요: 현대 C++ 프로그래밍에서는 컴파일 시간에 크기를 아는 배열이 필요할 때 C-style 배열보다std::array
를 사용하는 것이 좋습니다. 타입 안정성이 높고 사용이 편리하며 실수를 줄여줍니다.- 함수 인자 전달:
std::array
를 함수에 전달할 때는 큰 배열의 경우 불필요한 복사를 피하기 위해const
참조(const std::array<T, N>&
)로 전달하는 것이 효율적입니다. - Range-based for loop:
std::array
는 반복자를 지원하므로, C-style 인덱스 기반 루프보다 범위 기반for
루프를 사용하는 것이 더 깔끔하고 안전합니다.for (const auto& val : my_array2) { std::cout << val << "\n"; }
- 데이터 접근: 안전성이 중요하다면
.at()
을, 성능이 중요하다면[]
연산자를 사용하세요. 대부분의 경우[]
연산자의 성능 저하는 미미합니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : anonymous namespace (98, 11, 17) (2) | 2025.08.09 |
---|---|
Modern C++ : C-Style static function (98, 11) (1) | 2025.08.08 |
Modern C++ : static local variables (98, 11) (0) | 2025.08.07 |
Modern C++ : const vs constexpr (98, 11, 14, 17, 20) (0) | 2025.08.06 |
Modern C++ : type conversions (11, 14, 17, 20) (3) | 2025.08.05 |
Modern C++ : designated initializers (20) (0) | 2025.08.04 |
Modern C++ : enum concepts (11, 20) (1) | 2025.08.03 |
Modern C++ : enum vs enum class (98, 11) (1) | 2025.08.02 |