씹어먹는 C++ 13일차

❗참고 : https://modoocode.com/223

C++ 표준 템플릿 라이브러리 (Standard Template Library, STL)

  • 표준 STL은 std namespace에 존재함
  • STL = container + iterator + algorithm
  • 아래의 세 가지 라이브러리를 의미
    • 컨테이너(container) : 임의 타입의 객체를 보관
    • 반복자(iterator) : 컨테이너에 보관된 원소에 접근
    • 알고리즘(algorithm) : 반복자들을 가지고 일련의 작업을 수행

Container - std::vector

Sequence container

  • Like array
  • 객체를 순차적으로 보관
  • vector, list, deque

Associative container

  • key를 이용하여 value를 찾아줌

Iterator

  • Like container의 원소에 접근할 수 있는 포인터
  • iterator 멤버 타입으로 정의되어 있음

일반적인 사용 예 (using vector)

  • ex) vector 의 경우, 반복자를 얻기 위해 begin() 함수와 end() 함수를 사용함
#include <iostream>
#include <vector>

int main() {
  std::vector<int> v;
  v.push_back(10);
  v.push_back(20);
  v.push_back(30);

  for(std::vector<int>::iterator itr = v.begin() ; itr != v.end() ; ++itr) {
    std::cout << *itr << std::endl;  // 10\n20\n30
  }

  std::vector<int>::iterator itr = v.begin() + 2;
  std::cout << "3번째 원소 : " << *itr << std::endl;  // 30

  return 0;
}

범위 기반 for문 (range based for loop)

  • C++11 부터 지원
#include <iostream>
#include <vector>

using namespace std;

int main() {
  vector<int> v;

  v.push_back(10);
  v.push_back(20);
  v.push_back(30);

  // range-based for
  for (int elem : v) {
    cout << " 원소 : " << elem << endl;
    // LIKE elem = v[i];
  }

  return 0;
}

Container - std::list

  • 양방향 연결구조를 가진 자료형
  • vector 와 달리 임의의 위치에 있는 원소에 바로 접근할 수 없음
    • 시작 원소와 마지막 원소의 위치만 기억하고 있음
    • []at 함수가 정의되어 있지 않음 (특정 index를 이용해 위치를 찾는)
  • vector 에 비해 임의의 위치에 빠르게 데이터를 추가/삭제 가능
#include <iostream>
#include <list>

int main() {
  std::list<int> lst;

  lst.push_back(1);
  lst.push_back(2);
  lst.push_back(3);

  for (std::list<int>::iterator itr = lst.begin() ; itr != lst.end() ; ++itr) {
    std::cout << *itr << std::endl;
  }
  return 0;
}
  • vector와 다르게 itr+x 연산은 할 수 없음
  • 아래 연산만 가능
    • itr++ // itr ++
    • itr– // –itr

std::deque (deque, double ended queue)

  • vector 와 비슷하게 임의의 위치에 있는 원소에 접근 가능
  • vector 와 다르게
    • 맨 뒤 혹은 맨 앞에 원소를 추가/제거 시에 O(1)로 수행 가능
    • 원소들이 메모리 상에서 연속적으로 존재하지 않음
      • 이로 인해, 실제 데이터가 어디에 저장되었는지를 위한 추가적인 메모리가 필요함
      • libc++ 라이브러리의 경우, 1개 원소 보관 시 추가되는 비용이 8배 (!)
#include <iostream>
#include <deque>

template <typename T>
void printDq(std::deque<T>& dq) {
  std::cout << "[";
  for (const auto& elem : dq) {
    std::cout << elem << " ";
  }
  std::cout << "]" << std::endl;
}

int main() {
  std::deque<int> dq;

  dq.push_back(1);
  dq.push_back(2);
  dq.push_pront(3);

  std::cout << "초기 dq 상태" << std::endl;
  printDq(dq);
  // 3 1 2

  std::cout << "맨 앞의 원소 제거" << std::endl;
  dq.pop_front();
  printDq(dq);
  // 1 2
  
  return 0;
}

사용 예시

  • 상황에 따라 다른 라이브러리를 활용하지만 주로 고려해야할 점

  • 일반적인 상황에서는 보통 vector 를 사용
  • 중간에 원소를 추가하거나 제거하는 작업이 많고, 원소를 순차적으로 접근하면 list 를 사용
  • 맨 처음과 맨 마지막에 원소를 추가/삭제하는 작업이 많은 경우 deque 를 사용

Tags: , ,

Categories:

Updated: