컴공생의 다이어리

[c++] array container(std::array) 본문

Development/C & C++

[c++] array container(std::array)

컴공 K 2021. 1. 15. 04:23

std::array

c++의 std::array는 메모리를 자동으로 할당하고 해제하며, 원소의 타입과 배열 크기를 매개변수로 사용하는 클래스 템플릿이다.

아래는 int타입의 std::array 배열을 선언한 후, 원소 값을 설정하거나 화면에 출력하는 코드이다.

#include <iostream>
#include<array>
using namespace std;

int main() {
	//크기가 3인 int 타입 배열 생성
	std::array<int, 3> arr1;
	arr1[0] = 1;	//첫번째 원소를 1로 설정
	std::cout << "arr1 배열의 첫번째 원소 : "<< arr1[0] << "\n";

	//크기가 5인 int 타입 배열 생성 및 바로 초기화
	std::array<int, 5> arr2 = { 1,2,3,4,5 };
	std::cout << "arr2 배열의 원소들 : ";
	for (int i = 0; i < arr2.size(); i++) {
		std::cout << arr2[i] << " ";
	}
	std::cout << "\n";
	return 0;
}

실행결과

 

std::array는 기존 배열에서 사용했던 방식과 똑같이 배열 원소에 접근할 때 []연산자를 사용할 수 있다. 연산자에 접근하고자 하는 배열 원소 인덱스를 지정할 경우, 빠른 동작을 위해 전달된 인덱스 값이 배열의 크기보다 작은지를 검사하지는 않는다. 대신에 std::array는 at(index)함수를 제공한다. at(index)는 인자로 전달된 index값이 유효하지 않으면 std::out_of_range 예외를 발생시킨다.

  [index] at(index)
기능
c/c++에서 사용하는 배열의 기본 방식과 똑같이 배열 원소에 접근 배열 원소에 접근
빠른 동작을 위해 전달된 인덱스 값이 배열의 크기보다 작은지를 검사 X 인자로 전달된 index값이 유효하지 않으면 std::out_of_range 예외를 발생
속도 at() 함수가 [] 연산자보다 조금 느린편

아래는 크기가 5인 int타입의 std::array 배열에서 유효하지 않은 인덱스(여섯번째 원소)에 접근하면 아래와 같이 try catch문을 통해 예외 처리를 한다.

#include <iostream>
#include<array>
using namespace std;

int main() {
	//크기가 5인 int 타입 배열 생성 및 바로 초기화
	std::array<int, 5> arr = { 1,2,3,4,5 };
	try {
		std::cout << "arr의 첫번째 원소 : " << arr.at(0) << "\n";
		std::cout << "arr의 두번째 원소 : " << arr.at(1) << "\n";
		std::cout << "arr의 세번째 원소 : " << arr.at(2) << "\n";
		std::cout << "arr의 네번째 원소 : " << arr.at(3) << "\n";
		std::cout << "arr의 다섯번째 원소 : " << arr.at(4) << "\n";
		/////////////// 이전까지는 에러 발생 X ///////////////

		//std::out_of_range 예외 발생
		std::cout << "arr의 여섯번째 원소 : " << arr.at(5) << "\n";
	}
	catch(const std::out_of_range& ex){
		std::cerr << ex.what() << "\n";
	}
	return 0;
}

실행결과

 

std::array 객체를 다른 함수에 전달하는 방식은 기본 데이터 타입을 전달하는 것과 비슷하다. 값 또는 참조로 전달할 수 있고, const를 함께 사용할 수도 있다. 기존에 c/c++의 기본 배열을 함수에 전달할 때처럼 포인터 연산을 사용하거나 참조 또는 역참조 연산을 사용하지 않아도 된다. 그러므로 다차원 배열을 전달하는 경우에도 std::array를 사용하는 것이 가독성이 훨씬 좋다. 아래는 사용자 정의 함수 PRINT()에 std::array 배열을 값으로 전달하는 예제 코드이다.

#include <iostream>
#include<array>

void PRINT(std::array<int, 5> arr) {
	for (auto element : arr) {
		std::cout << element << " ";
	}
}
int main() {
	//크기가 5인 int 타입 배열 생성 및 바로 초기화
	std::array<int, 5> arr = { 1,2,3,4,5 };
	PRINT(arr);
	return 0;
}

실행결과

PRINT() 함수의 매개변수 데이터 타입에 전달받을 배열 크기가 고정되어 있기 때문에 다른 크기의 배열을 전달할 수 없다. 만일 std::array<int, 8>을 PRINT() 함수에 전달하면 컴파일러는 아래와 같이 함수 매개변수와 일치하지 않는다거나 또는 해당 매개변수 형식으로 변환할 수 없다는 에러메시지를 출력할 것이다.

다른 크기의 배열을 전달했을 때의 에러메시지

만일 다양한 크기의 std::array 객체에 대해 동작하는 배열 출력 함수를 만들고 싶다면 PRINT()를 함수 템플릿으로 선언하고, 배열 크기를 템플릿 매개변수로 전달하면 된다.

#include <iostream>
#include<array>
template<size_t N>
void PRINT(std::array<int, N> arr) {
	for (auto element : arr) {
		std::cout << element << " ";
	}
}
int main() {
	std::cout << "----- arr1 -----" << std::endl;
	//크기가 5인 int 타입 배열 생성 및 바로 초기화
	std::array<int, 5> arr1 = { 1,2,3,4,5 };
	PRINT(arr1);
	std::cout << "\n----------------" << std::endl;

	//크기가 8인 int 타입 배열 생성 및 바로 초기화
	std::cout << "----- arr2 -----" << std::endl;
	std::array<int, 8> arr2 = { 1,2,3,4,5,6,7,8 };
	PRINT(arr2);
	std::cout << "\n----------------" << std::endl;
	return 0;
}

실행결과

PRINT() 함수에 std::array 객체를 전달할 경우, 기본적으로 새로운 배열에 모든 원소가 복사(자동으로 깊은 복사 동작)된다. 이러한 불필요한 복사 비용을 피하고 싶다면 참조 또는 const 참조를 사용하면 된다.

void PRINT(std::array<int, N>& arr) {
	for (auto element : arr) {
		std::cout << element << " ";
	}
}

cf) 관련 게시물(클릭)

배열에 대한 출력을 하는 for 반복문을 사용할 때, 배열의 크기를 정확하게 지정하는 것은 매우 중요하다. 만약 인덱스 값이 배열 크기보다 같거나 커지면 에러가 발생한다.

 

 

begin() 함수와 end() 함수

위에서는 범위 기반 for 반복문의 auto 키워드를 사용하여 std::array의 모든 원소에 접근할 수 있었다. 이 방법 외에도 std::array는 begin()과 end()함수라는 멤버 함수를 제공한다. begin() 함수는 가장 첫번째 원소를 반환하고, end() 함수는 가장 마지막 원소의 위치(정확하게는 마지막 원소 다음 위치)를 반환한다. PRINT() 함수를 아래와 같이 작성할 수도 있다.

void PRINT(std::array<int, N>& arr) {
	for (auto it = arr.begin(); it != arr.end(); it++) {
		auto element = (*it);
		std::cout<<element<<" ";
	}
}

cf) begin()함수와 end()함수는 값이 아닌 위치를 반환하기 때문에 값을 사용하기 위해서 포인터(*)를 사용해야함

 

 

front() 함수, back() 함수, data() 함수

front() 함수는 배열의 첫번째 원소에 대한 참조(값)를 반환한다. back() 함수는 배열의 마지막 원소에 대한 참조를 반환한다. data() 함수는 배열 객체 내부에서 실제 데이터 메모리 버퍼를 가리키는 포인터를 반환한다. 반환된 포인터를 이용하여 다양한 포인터 연산을 수행할 수 있다.

#include <iostream>
#include<array>
int main() {
	//크기가 5인 int 타입 배열 생성 및 바로 초기화
	std::array<int, 5> arr = { 1,2,3,4,5 };
	std::cout << arr.front() << std::endl;
	std::cout << arr.back() << std::endl;
	std::cout << *(arr.data()+1) << std::endl;
	return 0;
}

실행결과

 

array container 멤버 함수 정리

가정 : array<int, 10> arr = {1,2,3,4,5,6,7,8,9,10};으로 arr 변수 명을 사용했다고 가정

함수 이름 함수 설명 함수 원형
arr.begin() 배열의 맨 첫번째 원소를 가리킴 (iterator와 사용) iterator begin() noexcept;
arr.end() 배열의 맨 마지막 "다음" 원소를 가리킴 (with iterator) iterator end() noexcept;
arr.rbegin() 배열을 거꾸로 했을때 첫번째 원소를 가리킴(with iterator) reverse_iterator rbegin() noexcept;
arr.rend() 배열을 거꾸로 했을때 마지막의 "다음" 원소를 가리킴 (with iterator) reverse_iterator rend() noexcept;
arr.cbegin(), cend() 위쪽 begin, end와 같지만 const가 붙어서 iterator를 이용해서 원소를 수정할 수 없음 const_iterator --() noexcept;
arr.crbegin(), crend() 위와 동일 const_reverse_iterator --() nocept;
arr.front() 배열의 맨 앞의 원소를 반환 reference front();
arr.back() 배열의 맨 뒤의 원소를 반환 reference back();
arr.data()
배열의 포인터 타입으로 반환(배열의 첫번째 주소를 반환) value_type* data() noexcept;
arr.fill(val) 배열의 인자를 val으로 다 바꿔줌 void fill(const value_type& val);
arr.swap(arr2) arr2의 배열 인자와 arr의 인자들을 교체
(이때, 길이와 타입이 같아야함)
void swap(array& arr) noexcept....;
arr.at(N) N번째 인자를 반환 reference operator ar(size_type n);
arr[N] N번째 인자를 반환 reference operator[](size_type n);
arr.empty()
비어있는지 확인 constexpr bool empty() noexcept;
arr.max_size()
배열의 최대 사이즈를 반환(size와 같음) constexpr size_type max_size() noexcept;
arr.size()
배열의 사이즈를 반환(max_size와 같음) constexpr size_type size() noexcept;

 

 

boycoding.tistory.com/213

 

C++ 07.21 - std::array 소개

std::array 소개 이전 포스트들에서 고정 배열(fixed array)과 동적 배열(dynamic array)을 배웠다. 두 가지 배열 모두 C++에 내장되어 있지만, 포인터로 형 변환되었을 시 배열 길이 정보가 손실되고, 동적

boycoding.tistory.com

blockdmask.tistory.com/332

 

[C++] array container 정리 및 사용법 (std::array)

안녕하세요. BlockDMask 입니다. <목차> 0. what is array container? 1. array container 헤더파일 2. array container 생성자 3. array container 멤버 함수 4. array container 예제 1 - size, empty, max_..

blockdmask.tistory.com

www.yes24.com/Product/Goods/95863013

 

코딩 테스트를 위한 자료 구조와 알고리즘 with C++

67개 문제 풀이로 익히는 C++ 자료 구조와 알고리즘!코딩 테스트 준비 및 최신 C++ 문법으로 알고리즘을 학습하자!C++ 자료 구조부터 그리디 알고리즘, 분할 정복 알고리즘, 그래프 알고리즘, 동적

www.yes24.com

 

728x90
Comments