Language/C++

[C++] STL (Standard Template Library) 2편 - iterator와 algorithm

검은 까마귀 2024. 1. 24. 15:01

2024.01.23 - [Language/C++] - [C++] STL (Standard Template Library) 1편 - Container

 

[C++] STL (Standard Template Library) 1편 - Container

저번에 포스팅 한 Template는 Generic Programing을 위한 C++의 문법이었다. 2024.01.23 - [Language/C++] - [C++] Template(템플릿) [C++] Template(템플릿) # Generic Programming 기존에 공부했던 JAVA에서는 제네릭 문법이 잇었

blaj2938.tistory.com

 

1편에서는 자료구조와 관련된 컨테이너라고 부르는 STL을 살펴보았다. 자바의 리스트나 맵이나 우리가 하는 자료구조형을 구현해둔 것이라 학습하는 것이 그렇게 어렵지 않았다.

(이름이 비슷하게 왜이렇게 많은지... 도커도 컨테이너인데)

 

이번에는 iterartor(반복자) 와 algorithm(알고리즘)에 대해서 알아보겠다.

 

# iterator(반복자)

일단 반복자의 정의 부터 알아보자.

  • 가리키는 요소의 값에 접근할 수 있어야함 ➡️ 참조연산자가 필요하다는 말
  • 반복자 사이의 대입 연산, 비교연산이 가능해야함 ➡️ 대입, 관계연산자가 필요하는 말
  • 가리키는 요소의 주변 요소로 이동할 수 있어야함 ➡️ 증가연산자나 감소연산자가 필요한다는 말

따로 쓰는 경우는 없고 STL 컨테이너들과 같이 쓰이거나 STL 알고리즘의 함수로 구현되어있다. 알고리즘에 대해 알아보면서 차차 코드로 넘어가보자

# Algorithm(알고리즘)

STL의 알고리즘은 일반적으로 사용하는 알고리즘에 대해서 효율적으로 구현해둔 것이다. 항상 빼놓을 수 없는 검색,변경, 정렬, 계산과 같은 것들을 다 함수로 만들어 둔것이다. 이는 위에서 말한 iterator와 컨테이너들을 사용해서 만들어져있다.

  • 읽기 알고리즘 (algorithm.h)
  • 변경 알고리즘 (algorithm.h)
  • 정렬 알고리즘 (algorithm.h)
  • 수치 알고리즘(numeric.h)

이제 코드로 한번 보겠다.

#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;


int main() {
	
	std::cout << "int:\t\t" << sizeof(int) << " bytes" << std::endl; // 주소록 비교를 위한
    std::cout << "long:\t\t" << sizeof(long) << " bytes";// 주소록 비교를 위한
	
	cout << "\n==============================\n";

	//백터에 값추가
    vector<int> vInt = {46,67,184,4,17,53};
	
	vector<long> vLong = {46,67,184,4,17,53};
    
    cout << "현재 int타입의 vector : ";
    for (int i : vInt) cout << i << " ";
	cout << endl; 
	cout << "현재 long타입의 vector : ";
    for (int i : vLong) cout << i << " ";
    cout << "\n========읽기 알고리즘=========\n";

	
	//읽기 알고리즘: find() -> 데이터 타입 int
    int num = 4;
    auto it = find(vInt.begin(), vInt.end(), num); //이 지점에 iteratort가 생긴다.
	
	cout << "vInt.begin()의 값: " << &*vInt.begin() << endl; // 시작점의Iterator의 주소값
	cout << "vInt.end()의 값: " << &*vInt.end() << endl; // 마지막 점의 다음의 Iterator의 주소값(가상) 
	cout << "4가 있는Iterator의 값: " <<&*it << endl; //4가 있는Iterator의 주소값
	
	cout << endl; 
	//C++에서는 포인터  - 포인터를 하게되면 두 포인터 사이의 요소의 갯수가 나온다.자료형을 나눈 4로 나눈 것
	cout << "4가 있는Iterator의 값 - vInt.begin()의 값: " << &*it - &*vInt.begin() <<endl;
	cout << endl;
	
    if (it == vInt.end()) { //iterator 값이 vector의 마지막 데이터의 다음과 똑같으면 찾을 수 없다.
        cout << num << "은 찾을 수 없습니다.\n";
    }
    else { //찾았고 num =4 지점의 iterator 값과 시작점의 iterator 값의 차가 인덱스의 위치이다.(위에 내용도 확인)
        cout << num << "는 존재하며 인덱스는 " << it - vInt.begin() << " 입니다.\n";
    }
    cout << "\n========long 타입==========\n";
	
	//읽기 알고리즘: find() -> 데이터 타입 long
	long numLong = 17;
    auto iter = find(vLong.begin(), vLong.end(), numLong); //이 지점에 iteratort가 생긴다.
	
	cout << "vLong.begin()의 값: " << &*vLong.begin() << endl; // 시작점의Iterator의 주소값
	cout << "vLong.end()의 값: " << &*vLong.end() << endl; // 마지막 점의 다음의 Iterator의 주소값(가상) 
	cout << "17가 있는Iterator의 값: " <<&*iter << endl; //4가 있는Iterator의 주소값
	
	cout << endl; 
	//C++에서는 포인터  - 포인터를 하게되면 두 포인터 사이의 요소의 갯수가 나온다.자료형을 나눈 4로 나눈 것
	cout << "17가 있는Iterator의 값 - vLong.begin()의 값: " << &*iter - &*vLong.begin() <<endl;
	cout << endl;
	
    if (iter == vLong.end()) { //iterator 값이 vector의 마지막 데이터의 다음과 똑같으면 찾을 수 없다.
        cout << numLong << "은 찾을 수 없습니다.\n";
    }
    else { //찾았고 num =4 지점의 iterator 값과 시작점의 iterator 값의 차가 인덱스의 위치이다.(위에 내용도 확인)
        cout << numLong << "는 존재하며 인덱스는 " << iter - vLong.begin() << " 입니다.\n";
    }
	
    cout << "\n========변경 알고리즘=========\n";
	
	//copy알고리즘
	cout << "\n========copy()=========\n";
	vector<int> vc;
	auto mid = vInt.begin() + vInt.size() /2; // vector의 절반만 복사하기
	copy(vInt.begin(), mid , back_inserter(vc));
	cout << "vector 복사: ";
	for (int i : vc) cout << i << " ";
	cout << endl; 
	
	//swap알고리즘
	cout << "\n========swap()=========\n";
	vector<int>().swap(vc); //포인터가 nullptr을 가르키면서 메모리가 해제됨
	if(vc.capacity() == 0){
		cout << "swap으로 인한 메모리가 해제 되었습니다" << endl;
	}
    return 0;
}

 

내가 작성한 함수보다 더 많은 함수들이 있다. 대표적으로 자주 사용된다고 하는 함수만 작성한 것이 때문에 더 자세히 알고싶으면 공식 문서를 참고해서 학습하면 될거 같다. 머리속에 달달 외울수는 없으니 공식문서를 최대한 많이 참고하자!

https://cplusplus.com/reference/vector/vector/swap/

 

https://cplusplus.com/reference/vector/vector/swap/

foo contains: 200 200 200 200 200 bar contains: 100 100 100

cplusplus.com


실습을 진행하면서 가장 어려웠던건 Iterator의 개념이었다. Iterator가 어떠한 다른 자료형으로 그려질 수 있다고 생각했는데 내 생각과는 다르게 추상화 되어있는 객체이기때문에 연산이 되는 과정 자체가 달랐다. Iterator는 주소값을 나타는 것이고 일반적인 연산이 불가능했다. (정수 연산 같이 사칙연산 불가.....)

 

또한, 언메니지드 언어이기도 하고 주소값으로 동작하는 함수들도 많아서 자꾸 써봐야 알겠지만 디버깅을 할때 주소값에 유의해서 코드를 작성하거나 메모리 해제도 필요해 보인다.

비로소 자바가 꽤나 잘 만들어져 매니지드 언어라고 불리는 이유를 알게된거 같다. 그래도 C++은 꼭 컴퓨터 구조를 이해할때 필요하다고 생각된다.

반응형

'Language > C++' 카테고리의 다른 글

[C++] STL (Standard Template Library) 1편 - Container  (0) 2024.01.23
[C++] Template(템플릿)  (0) 2024.01.23
[C++] Class & 접근제어지시어  (0) 2024.01.22
[C++] Structure Type(구조체)  (0) 2024.01.19
[C++] Pointer(포인터)  (0) 2024.01.18