해당 글은 공부를 하면서 적은 글이기 때문에 틀릴 수 있습니다. 참고용으로만 봐주세요~
0. 개요
vector를 다시 공부하면서 찾아보니, 기존에 사용하던 c스타일의 배열 뿐아니라 MSDN에서는 std::array를 사용할 것을 권장한다는 것을 알게되었습니다.
따라서 이번 글에서는 배열에 대해 간단하게 알아본 뒤, std::array는 어떤 것인가에 대해 공부하겠습니다.
1. 배열 (Array)
컴퓨터 공학에서 배열(Array)이란 번호(Index)와 그에 대응하는 데이터들로 이루어진 자료구조를 뜻합니다.
일반적으로는 배열은 같은 종류(Type)의 데이터들이 순차적으로 메모리에 저장됩니다.
배열을 사용하는 이유는 많은 수의 데이터를 저장하기 위한 변수를 선언할 때 일반 변수로 관리하기가 어렵기 때문에 하나의 변수(배열)를 선언해서 많은 데이터를 한번에 순차적으로 처리할 수 있기 때문입니다.
void main()
{
int iArray[5];
return;
}
배열은 위 예제 코드와 같이 선언할 수 있습니다.
일반 변수와 같이 자료형을 먼저 작성하고, 배열의 이름(변수명)을 작성해 선언합니다.
이때, 변수명 뒤에 [] 연산자를 이용해 배열의 크기를 지정해줍니다.
주의할 점은 배열은 선언할 때 반드시 크기를 명시해주어야 하며, 크기에는 변수가 아닌 상수만 들어올 수 있습니다.
상수만 들어올 수 있는 이유는 배열의 경우 컴파일 타임에 메모리를 할당 받기 때문에 중간에 변할 수 없습니다. 따라서 해당 배열의 크기도 중간에 변경할 수 없습니다.
이런 이유 때문에 중간에 크기가 유동적으로 변경되어야 할때는 동적 배열을 사용해주어야 합니다.
배열의 초기화는 다음과 같습니다.
void main()
{
int iArray[5] = { 1, 2, 3, 4, 5 };
int iArray2[] = { 1, 2, 3, 4, 5 };
int iArray3[5] = {};
return;
}
초기화를 해준다면, 배열의 크기는 직접 명시해주지 않아도 자동으로 크기가 정해집니다.
만약 iArray3과 같이 크기만 명시해준다면 배열의 요소들은 모두 0으로 초기화 됩니다.
배열의 요소에 접근해보고 싶을 때는 []연산자를 사용해 접근해줍니다.
void main()
{
int iArray[5] = { 1, 2, 3, 4, 5 };
int iNum_4 = iArray[3];
return;
}
주의 할 점은 배열의 시작 Index는 1이 아닌 0이라는 점입니다.
[] 연산자를 이용해 배열의 요소 범위를 초과해 접근하면 런타임 에러가 발생합니다.
iArray와 같이 선언된 배열은 vector와 마찬가지로 배열의 시작점의 주소를 담고 있습니다.
왜 시작주소를 가지고 있냐면, 배열은 메모리상 연속적인 공간을 할당받기 때문입니다.
(배열의 요소는 순차적으로 연속된 메모리에 저장된다.)
동적 배열의 경우 malloc() & free()를 이용해 직접 구현할 수 있고, 클래스로 만들면 new & delete를 이용해 구현해 줄 수 있습니다. 뿐만 아니라 vector container를 사용해 만들 수 있습니다.
이렇게 정말 단순하고 간단하게만 C스타일의 배열에 대해 살펴 보았습니다.
그렇다면 MSDN에서 권장하는 std::array는 어떤 것인지 살펴 보겠습니다.
2. std::array
고정 배열의 경우 포인터로 형 변환되었을 시 배열 길이 정보가 손실되는 문제가 있었습니다.
이러한 문제를 해결하기 위해 C++ 표준라이브러리는 배열 관리를 쉽게 해주는 std::array가 있습니다.
C++ 11에서 소개된 std::array는 함수에 전달할 때 포인터로 형 변환되지 않는 고정 길이 배열이다.
array를 사용하기 위해서는 먼저 를 포함해주어야 한다.
std::array도 고정 배열 선언과 마찬가지로 컴파일 타임에 array의 크기를 할당받기 때문에 반드시 선언시 배열의 크기를 명시해주어야 합니다.
#include <array>
using namespace std;
void main()
{
array<int, 5> arr_Array = { 1, 2, 3, 4, 5 }; // 초기화 리스트
array<int, 5> arr_Array2{ 1, 2, 3, 4, 5 }; // 유니폼 초기화
int a = 0;
return;
}
std::array는 초기화 리스트(initalizer list) 또는 유니폼 초기화(uniform initialization)를 사용해 초기화 할 수 있습니다.
다만 C 스타일의 고정 배열과는 다르게, std::array의 배열크기를 생략할 수 없습니다.
void main()
{
int arr_CArray[] = { 1,2, 3, 4, 5 }; // 가능
array<int, > arr_Array3 = { 1, 2, 3, 4, 5 }; // 불가능
return;
}
vector와 C 스타일 고정배열과 마찬가지로 []연산자를 이용해 배열의 원하는 요소 값에 쉽게 접근할 수 있습니다.
void main()
{
array<int, 5> arr_Array = { 1, 2, 3, 4, 5 };
int arr_CArray[] = { 1,2, 3, 4, 5 };
int inum_Index3 = arr_Array[3];
inum_Index3 = arr_CArray[3];
return;
}
마찬가지로 배열의 시작은 0부터 시작하며, 일반 배열과 마찬가지로 유효 범위 검사를 진행하지 않으므로 잘못된 index가 제공되면 오류가 발생합니다.
일반 배열과 달리 vector에도 존재했던 .at()함수가 std::array에도 존재해 유효 범위 검사를 진행하며 원하는 요소에 접근할 수 도 있습니다.
void main()
{
array<int, 5> arr_Array = { 1, 2, 3, 4, 5 };
int inum_Index3 = arr_Array[3];
inum_Index3 = arr_Array.at(3);
return;
}
만약 범위를 벗어나 접근하게 되면, std::out_of_range를 반환해줍니다.
vector에서 설명드렸다 싶이 at() 함수는 유효 범위 검사를 하기 때문에 [] 연산자 보다 안전하지만, 속도는 더 느립니다.
std::array의 멤버 함수
◈ array();
기본 생성자는 제어되는 시퀀스를 초기화되지 않은 상태(또는 기본 시퀀스를 초기화한 상태로)로 유지합니다.
초기화 되지 않은 배열을 만들려면 이 생성자를 사용하면 됩니다.
std::array는 기본 생성자 뿐 아니라 복사 생성자도 지원합니다.
◈ arr.fill(num);
C++ 11 이전에 있던 assign() 함수가 사라지고, fill() 함수가 추가되었습니다.
array의 모든 요소를 num으로 변경해 채워줍니다.
(MSDN에 따르면 배열을 지우고 전달받은 num을 빈 배열에 복사한다고 되어있습니다.)
◈ arr.at(num);
num 위치에 있는 요소에 접근합니다. (참조로 반환한다.)
뿐만 아니라 유효 범위 검사를 함께 진행합니다. (잘못 접근할 경우 out_of_range를 반환합니다.)
◈ arr.back();
배열의 마지막 요소에 접근합니다. (참조로 반환합니다.)
◈ arr.begin();
배열의 시작점 즉, 첫 번째 요소를 가리키는 iterator를 반환합니다.
◈ arr.end();
배열의 끝을 반환 받습니다. 즉, end iterator를 반환합니다.
◈ arr.cbegin();
배열의 첫 번째 요소에 대한 const_iterator를 반환합니다.
배열이 비어있을 경우 cend()를 반환합니다. (end iter를 반환한다는 의미)
◈ arr.cend();
배열 끝의 바로 다음을 가리키는 const_iterator를 반환합니다.
◈ arr.crbegin();
역방향 배열의 첫 번째 요소에 대해 const_iterator를 반환합니다.
◈ arr.crend();
역방향 배열 끝에 대해 const_iterator를 반환합니다.
◈ arr.data();
첫 번째 요소의 주소를 가져옵니다. (즉, 반환값을 역참조하면 첫 번째 요소 값이 나온다.)
◈ arr.empty();
배열이 비어있는지 확인합니다.
◈ arr.front();
첫 번째 요소에 접근합니다. (참조로 반환합니다.)
◈ arr.max_size();
요소 수를 계산합니다.
◈ arr.rbegin();
제어되는 역방향 시퀀스의 시작 즉, 배열의 끝 다음을 가리키는 end iterator를 반환합니다.
reverse_iterator와 const_reverse_iterator로 반환됩니다.
◈ arr.rend();
제어되는 역방향 시퀀스의 끝 즉, 배열의 시작인 첫 번째 요소를 가리키는 reverse_iterator를 반환합니다.
reverse_iterator와 const_reverse_iterator로 반환됩니다.
◈ arr.size();
배열의 요소 수를 계산합니다.
◈ arr.swap(arr2);
두 배열의 내용을 바꿉니다.
vector와 마찬가지로 end iterator를 역참조하면 에러가 발생한다.
sizeof()는 배열의 크기( 배열 요소의 자료형 * 배열의 길이)이고, .size()는 배열의 길이를 반환하므로 햇갈리면 안된다.
3. 참고 문헌
배열 (C++)
표준 C++ 프로그래밍 언어로 네이티브 배열 형식을 선언하고 사용하는 방법을 알아봅니다.
learn.microsoft.com
C++ 07.21 - std::array 소개
std::array 소개 이전 포스트들에서 고정 배열(fixed array)과 동적 배열(dynamic array)을 배웠다. 두 가지 배열 모두 C++에 내장되어 있지만, 포인터로 형 변환되었을 시 배열 길이 정보가 손실되고, 동적
boycoding.tistory.com
C/C++ 배열 사용법
안녕하세요 열코입니다. 이번시간에는 C/C++에서 배열의 사용법에 대해 알아보겠습니다. 컴퓨터 공학에서 배열(array)이란 번호(index)와 그에 대응하는 데이터들로 이루어진 자료구조를 뜻합니다.
yeolco.tistory.com
array 클래스(C++ 표준 라이브러리)
자세한 정보: 배열 클래스(C++ 표준 라이브러리)
learn.microsoft.com
'프로그래밍 > 자료구조' 카테고리의 다른 글
C++ Map Conatiner (1) | 2024.01.31 |
---|---|
C++ List Container (0) | 2024.01.30 |
C++ Vector Container (1) | 2024.01.30 |
[STL] 효과적인 컨테이너 요리 (0) | 2023.07.19 |