Skip to content

Latest commit

Β 

History

History
256 lines (184 loc) Β· 9.29 KB

STL.md

File metadata and controls

256 lines (184 loc) Β· 9.29 KB

STL

μž‘μ„±μž : λ°•μž¬μš©

  • C++의 κΈ°λ³Έ! STL이 무엇인지 μ΄ν•΄ν•˜κΈ°
  • STL을 직접 μ‚¬μš©ν•΄λ³΄κΈ°
Table of Contents

STL

STL은 Standard Template Library둜 C++λ₯Ό μœ„ν•œ ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬λ‘œμ„œ μ»¨ν…Œμ΄λ„ˆ, 반볡자, μ•Œκ³ λ¦¬μ¦˜ 그리고 ν•¨μˆ˜μžλΌκ³  λΆˆλ¦¬λŠ” λ„€κ°€μ§€μ˜ κ΅¬μ„±μš”μ†Œλ₯Ό μ œκ³΅ν•œλ‹€. (C++ : Black Book)
C++μ—μ„œ vector, queue λ“± λ‹€μ–‘ν•œ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ„ #include ν•˜μ—¬ μ‚¬μš©ν•œ 적이 μžˆλŠ”κ°€? 이것듀이 STL의 일뢀이닀.

μš°λ¦¬κ°€ μ™œ STL을 λ°°μ›Œμ•Ό ν•˜λŠ”κ°€?

초창기 STL은 μ—΄μ•…ν•œ μ„±λŠ₯κ³Ό 버그에 μ˜ν•΄μ„œ κ°œλ°œμžλ“€μ˜ ν˜Έμ‘μ„ λŒμ–΄λ‚Ό 수 μ—†μ—ˆμ§€λ§Œ μ΅œκ·Όμ—λŠ” STL 없이 C++을 λ…Όν•  수 μ—†μ„λ§ŒνΌ μ€‘μš”ν•΄μ‘Œλ‹€. STL을 μ‚¬μš©ν•¨μœΌλ‘œμ„œ 효율적인 ν”„λ‘œκ·Έλž˜λ°μ΄ κ°€λŠ₯ν•΄μ‘Œλ‹€.

STL μ»¨ν…Œμ΄λ„ˆ

일반적으둜 μ»¨ν…Œμ΄λ„ˆλŠ” λ‹€λ₯Έ 객체듀을 λ³΄κ΄€ν•˜λŠ” ν•˜λ‚˜μ˜ μ»€λ‹€λž€ λ³΄κ΄€μ†ŒλΌκ³  λ³Ό 수 μžˆλ‹€. STL μ»¨ν…Œμ΄λ„ˆμ˜ 경우 클래슀 ν…œν”Œλ¦Ώμ˜ ν˜•νƒœλ‘œ κ΅¬ν˜„λ˜μ–΄ 있기 λ•Œλ¬Έμ— μž„μ˜μ˜ νƒ€μž… μ›μ†Œλ“€μ„ μœ„ν•œ μ»¨ν…Œμ΄λ„ˆλ₯Ό λ§Œλ“€ 수 μžˆλ‹€. ν‘œμ€€ λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œλŠ” μ—¬λŸ¬κ°€μ§€ ν˜•νƒœμ˜ μ»¨ν…Œμ΄λ„ˆλ₯Ό μ œκ³΅ν•œλ‹€.
μ‹œν€€μŠ€ μ»¨ν…Œμ΄λ„ˆ - Sequence Container

ex) vector, deque, array, priority_queue, list

μ—°κ΄€ μ»¨ν…Œμ΄λ„ˆ - Associative Container

ex) set, map, multiset, multimap, unordered_set, unordered_map

STL 반볡자

iterator

포인터와 λΉ„μŠ·ν•œ κ°œλ…μœΌλ‘œ μ»¨ν…Œμ΄λ„ˆμ˜ μ›μ†Œλ₯Ό 가리킀고, κ°€λ¦¬ν‚€λŠ” μ›μ†Œμ— μ ‘κ·Όν•˜μ—¬ μˆœνšŒκ°€ κ°€λŠ₯ν•œ 반볡자. ꡬ체적으둜 μ„€λͺ…ν•˜μžλ©΄ μ»¨ν…Œμ΄λ„ˆμ—μ„œ λ³΄μœ ν•˜λŠ” λ‚΄λΆ€ 데이터λ₯Ό μˆœνšŒν•  수 μžˆλŠ” 객체둜 μ»¨ν…Œμ΄λ„ˆμ˜ νŠΉμ • μœ„μΉ˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€. C++μ—μ„œλŠ” 아직 자료λ₯Ό 포인터 λ‹¨μœ„λ‘œ κ΄€λ¦¬ν•˜κΈ°μ— ν•΄λ‹Ή 자료의 μœ„μΉ˜μ—μ„œ 데이터에 μ ‘κ·Όν•˜κ³  μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œ κ·Έ μœ„μΉ˜μ— μ €μž₯된 자료ꡬ쑰λ₯Ό μ½λŠ”λ° λ°˜λ³΅μžκ°€ ν•„μš”ν•˜λ‹€.

ex1) begin() - μ»¨ν…Œμ΄λ„ˆμ˜ 첫번째 μœ„μΉ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 반볡자λ₯Ό λ°˜ν™˜

ex2) end() - μ»¨ν…Œμ΄λ„ˆμ˜ λ§ˆμ§€λ§‰ μœ„μΉ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 반볡자λ₯Ό λ°˜ν™˜

  1. *μ—°μ‚°μž : μ§€κΈˆ ν˜„μž¬ μœ„μΉ˜μ˜ μ›μ†Œλ₯Ό λ°˜ν™˜
  2. ++μ—°μ‚°μž : μ»¨ν…Œμ΄λ„ˆμ˜ λ‹€μŒ μ›μ†Œλ₯Ό κ°€λ¦¬ν‚€λŠ” μœ„μΉ˜λ‘œ λ°˜λ³΅μžκ°€ 이동
  3. --μ—°μ‚°μž : μ»¨ν…Œμ΄λ„ˆμ˜ 이전 μ›μ†Œλ₯Ό κ°€λ¦¬ν‚€λŠ” μœ„μΉ˜λ‘œ λ°˜λ³΅μžκ°€ 이동
  4. = μ—°μ‚°μž : λ°˜λ³΅μžκ°€ μ°Έμ‘°ν•˜λŠ” μ›μ†Œμ˜ μœ„μΉ˜λ₯Ό λ‹€λ₯Έ λ°˜λ³΅μžμ— ν• λ‹Ή
  5. ==, != μ—°μ‚°μž : 비ꡐ μ—°μ‚°μž

STL μ•Œκ³ λ¦¬μ¦˜

μ •λ ¬, μ‚­μ œ, 검색, μ—°μ‚° 등을 ν•΄κ²°ν•˜λŠ” μΌλ°˜ν™”λœ 방법을 μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ Template

  1. κ³„μˆ˜ μ•Œκ³ λ¦¬μ¦˜ count(), count_if()
    주어진 κ°’κ³Ό μΌμΉ˜ν•˜κ±°λ‚˜, 쑰건에 λ§žλŠ” μš”μ†Œλ“€μ˜ 개수λ₯Ό count

  2. 탐색 μ•Œκ³ λ¦¬μ¦˜ search(), search_n(), find(), find_if(), find_end(), binary_search()
    주어진 κ°’κ³Ό μΌμΉ˜ν•˜κ±°λ‚˜, 쑰건에 λ§žλŠ” μš”μ†Œλ₯Ό λ°˜ν™˜

  3. 비ꡐ μ•Œκ³ λ¦¬μ¦˜ equal(), mismatch(), lexicographical_compare()
    λ‘κ°œμ˜ μš”μ†Œκ°€ 같은지 비ꡐ

  4. μ΄ˆκΈ°ν™” μ•Œκ³ λ¦¬μ¦˜ fill(), generate()
    μ§€μ •λœ λ²”μœ„μ˜ μš”μ†Œλ₯Ό μ§€μ •ν•œ κ°’μœΌλ‘œ ν• λ‹Ή 및 ν•¨μˆ˜μ˜ λ°˜ν™˜ κ°’ ν• λ‹Ή

  5. λ³€κ²½ μ•Œκ³ λ¦¬μ¦˜ for_each(), transform()
    μ§€μ •λœ λ²”μœ„μ˜ λͺ¨λ“  μš”μ†Œμ— λŒ€ν•œ μ—°μ‚°κ³Ό ν•¨μˆ˜ 적용

  6. 볡사 μ•Œκ³ λ¦¬μ¦˜ copy()
    ν•˜λ‚˜μ˜ ꡬ간을 λ‹€λ₯Έ κ΅¬κ°„μœΌλ‘œ 볡사

  7. μ‚­μ œ μ•Œκ³ λ¦¬μ¦˜ remove(), unique()
    μ§€μ •λœ 값을 κ°€μ§€λŠ” μš”μ†Œλ₯Ό μ‚­μ œν•˜κ±°λ‚˜, μ€‘λ³΅λœ μš”μ†Œλ₯Ό μ‚­μ œ

  8. λŒ€μΉ˜ μ•Œκ³ λ¦¬μ¦˜ replace()
    μ§€μ •λœ κ΅¬κ°„μ—μ„œ μš”μ†Œκ°€ μ§€μ •λœ κ°’κ³Ό μΌμΉ˜ν•˜λ©΄ λŒ€μΉ˜κ°’μœΌλ‘œ λ°”κΏˆ

  9. μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜ sort()
    μ§€μ •λœ μ •λ ¬ 기쀀에 λ”°λΌμ„œ κ΅¬κ°„μ˜ μš”μ†Œλ“€μ„ μ •λ ¬

  10. λΆ„ν•  μ•Œκ³ λ¦¬μ¦˜ partition()
    μ§€μ •λœ κ΅¬κ°„μ˜ μš”μ†Œλ“€μ„ 쑰건에 λ”°λΌμ„œ λ‘κ°œμ˜ μ§‘ν•©μœΌλ‘œ λ‚˜λˆ”

μ΄λŸ¬ν•œ 것듀이 STL에 기본으둜 λ‚΄μž₯된 μ•Œκ³ λ¦¬μ¦˜μ΄λΌλ‹ˆ 정말 C++ STL이 λ†€λžμ§€ μ•Šμ€κ°€?

STL ν•¨μˆ˜μž

STL ν•¨μˆ˜μžλž€ ν•¨μˆ˜ 객체와 같은 말둜, operator() μ—°μ‚°μžλ₯Ό μ˜€λ²„λ‘œλ”©ν•œ 클래슀 객체이닀. μš°λ¦¬κ°€ C++을 μ‚¬μš©ν•  λ•Œ sort(v.begin(), v.end(), less<int>()); 의 μ„Έλ²ˆμ§Έ 인자 less, greaterλ₯Ό μ‚¬μš©ν–ˆλ˜ 기얡이 μžˆλŠ”κ°€?
이것이 λ°”λ‘œ ν•¨μˆ˜μ²˜λŸΌ λ™μž‘ν•˜λŠ” 객체인 ν•¨μˆ˜μžμ΄λ‹€.

μš°λ¦¬μ™€ 같은 C++ κ°œλ°œμžλŠ” ν•¨μˆ˜μžλ₯Ό μ΄μš©ν•œ ν•¨μˆ˜λ₯Ό 많이 μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€. ν•¨μˆ˜ 포인터λ₯Ό 인자둜 μ‚¬μš©ν–ˆμ„ 경우의 단점은 λ°˜ν™˜κ°’κ³Ό μΈμžκ°€ λ™μΌν•œ ν•¨μˆ˜μ— λŒ€ν•΄μ„œλ§Œ λ™μž‘ν•˜κΈ° λ•Œλ¬Έμ— λ²”μš©μ„±μ΄ 떨어지기 λ•Œλ¬Έμ΄λ‹€.

비ꡐ ν•¨μˆ˜μž

비ꡐ μ—°μ‚° κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜μž
less(), greater(), equal_to(), greater_equal() 등이 μ‘΄μž¬ν•œλ‹€.

μ‚°μˆ  ν•¨μˆ˜μž

μ‚°μˆ  μ—°μ‚° κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜μž
plus(), minus(), multiplies(), divides() 등이 μ‘΄μž¬ν•œλ‹€.

논리 ν•¨μˆ˜μž

논리 μ—°μ‚° κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λŠ” ν•¨μˆ˜μž
logical_and(), logical_or(), logical_not() 등이 μ‘΄μž¬ν•œλ‹€.

plus ν•¨μˆ˜μžλ₯Ό μ‚¬μš©ν•˜λŠ” μ˜ˆμ‹œ

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

void main( )
{
    vector<int> v1;
    vector<int> v2;


    v1.push_back(10); 

    v1.push_back(20);
    v1.push_back(30);

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

    for(int i = 0 ; i < v1.size() ; i++)
        cout << v1[i] << " "; // 10, 20, 30
    cout << endl;

    for(int i = 0 ; i < v2.size() ; i++)
        cout << v2[i] << " "; // 1, 2, 3
    cout << endl;

    transform(v1.begin(), v1.end(), v2.begin(), v1.begin(), plus<int>());

    for(int i = 0 ; i < v1.size() ; i++)
        cout << v1[i] << " "; // 11, 22, 33
    cout << endl;
}

ν•¨μˆ˜ μ–΄λŒ‘ν„° (function adaptor)

μ–΄λŒ‘ν„°λž€ μ»¨ν…Œμ΄λ„ˆμ˜ μΈν„°νŽ˜μ΄μŠ€ λ˜λŠ” ν•¨μˆ˜μžμ˜ κΈ°λŠ₯을 λ³€κ²½ν•˜λŠ” μ»΄ν¬λ„ŒνŠΈλ₯Ό λ§ν•œλ‹€. 기쑴의 μ»¨ν…Œμ΄λ„ˆλ₯Ό μ΄μš©ν•΄μ„œ μŠ€νƒμ„ κΎΈλ―Έκ³  싢을 λ•Œμ—λŠ” μŠ€νƒ μ–΄λŒ‘ν„°λ₯Ό, ν•¨μˆ˜μžμ˜ 의미λ₯Ό λ³€κ²½ν•  λ•ŒλŠ” λ°”μΈλ”λ‚˜ λΆ€μ •μžλ₯Ό μ‚¬μš©ν•œλ‹€.

  • 바인더(binder)
    λ‘κ°œμ˜ 인자λ₯Ό ν•„μš”λ‘œ ν•˜λŠ” 이항 ν•¨μˆ˜ 객체의 인자 ν•˜λ‚˜λ₯Ό κ³ μ •μ‹œμΌœ 인자λ₯Ό ν•˜λ‚˜λ§Œ μš”κ΅¬ν•˜λŠ” 단항 ν•¨μˆ˜ 객체둜 λ³€ν™˜

  • λΆ€μ •μž(negator)
    ν•¨μˆ˜ 인자둜 μ‚¬μš©λ˜λŠ” 쑰건자의 의미λ₯Ό λ°˜λŒ€λ‘œ λ³€ν™˜

  • ν•¨μˆ˜ 포인터 μ–΄λŒ‘ν„°(adaptors for pointers to functions)
    λ‹¨ν•­μ΄λ‚˜ 이항 ν•¨μˆ˜ 포인터λ₯Ό λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ μ–΄λŒ‘ν„°μ™€ μ‚¬μš©ν•  수 μžˆλ„λ‘ 도움

  • 멀버 ν•¨μˆ˜ 포인터 μ–΄λŒ‘ν„°(adaptors for pointers to member functions)
    λ‹¨ν•­μ΄λ‚˜ 이항 멀버 ν•¨μˆ˜ 포인터λ₯Ό λΌμ΄λΈŒλŸ¬λ¦¬κ°€ μ œκ³΅ν•˜λŠ” ν•¨μˆ˜ μ–΄λŒ‘ν„°μ™€ μ‚¬μš©ν•  수 μžˆλ„λ‘ 도움

바인더 μ–΄λŒ‘ν„°

  • bind1st
    ν•¨μˆ˜μžμ— μ „λ‹¬λ˜λŠ” λ‘κ°œμ˜ 인자 쀑 첫번째 인자λ₯Ό κ³ μ •κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” 바인더

  • bind2nd
    ν•¨μˆ˜μžμ— μ „λ‹¬λ˜λŠ” λ‘κ°œμ˜ 인자 쀑 λ‘λ²ˆμ§Έ 인자λ₯Ό κ³ μ •κ°’μœΌλ‘œ μ‚¬μš©ν•  수 μžˆλ„λ‘ λ„μ™€μ£ΌλŠ” 바인더

less ν•¨μˆ˜μžμ— bind1st μ–΄λŒ‘ν„°λ₯Ό μ”Œμš΄ μ˜ˆμ‹œ

#include <iostream>
#include <functional>
using namespace std;
 
int main(void){
    // 첫 인자λ₯Ό 10으둜 κ³ μ •
    binder1st<less<int>> binder = bind1st (less<int>(), 10);
 
    cout << binder(5) << ':' << less<int>()(10, 5) << endl;
    cout << binder(10) << ':' << less<int>()(10, 10) << endl;
    cout << binder(20) << ':' << less<int>()(10, 20) << endl;
 
    cout << "== ==" << endl;
 
    // μž„μ‹œ 객체 μ‚¬μš©
    cout << bind1st(less<int>(), 10) (5) << ':' << less<int>()(10, 5) << endl;
    cout << bind1st(less<int>(), 10) (10) << ':' << less<int>()(10, 10) << endl;
    cout << bind1st(less<int>(), 10) (20) << ':' << less<int>()(10, 20) << endl;
 
}

μ‹€ν–‰ κ²°κ³Ό

0:0
0:0
1:1
== == 
0:0
0:0
1:1

λΆ€μ •μž μ–΄λŒ‘ν„°

ref

  • not1
    인자둜 μ „λ‹¬λœ 단항 쑰건자의 의미λ₯Ό λ°˜λŒ€λ‘œ λ³€ν™˜

5의 λ°°μˆ˜μΈμ§€ ν™•μΈν•˜λŠ” isMulti5 ν•¨μˆ˜λ₯Ό λ§Œλ“€μ—ˆλ‹€κ³  κ°€μ •ν–ˆμ„ λ•Œ not1(isMulti5()); 을 μ‚¬μš©ν•˜λ©΄ 5의 λ°°μˆ˜κ°€ μ•„λ‹Œκ²ƒλ§Œ ν™•μΈν•˜κ²Œ λœλ‹€.

  • not2
    인자둜 μ „λ‹¬λœ 이항 쑰건자의 의미λ₯Ό λ°˜λŒ€λ‘œ λ³€ν™˜

ex) sort(v.begin(), v.end(), compare());을 μ˜€λ¦„μ°¨μˆœμ΄λΌκ³  κ°€μ •ν–ˆμ„ λ•Œ `sort(v.begin(), v.end(), not2(compare())); 은 λ‚΄λ¦Όμ°¨μˆœμ΄ λœλ‹€.

ν•¨μˆ˜ 포인터 μ–΄λŒ‘ν„°

ν•¨μˆ˜ ν¬μΈν„°λŠ” 객체가 μ•„λ‹ˆλ―€λ‘œ μ–΄λŒ‘ν„°λ₯Ό μ μš©ν•  수 μ—†λŠ”λ° μ•„λž˜μ˜ ν•¨μˆ˜ 포인터 μ–΄λŒ‘ν„°λ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ ν•¨μˆ˜ 포인터λ₯Ό 객체둜 포μž₯ν•˜κ²Œ 되고 이 ν›„ 바인더, λΆ€μ •μž λ“±μ˜ μ–΄λŒ‘ν„°λ₯Ό μ μš©ν•  수 μžˆλ‹€.

  • ptr_fun
    단항 ν•¨μˆ˜λ₯Ό ν•¨μˆ˜ μ–΄λŒ‘ν„°μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ„λ‘ 지원
bool IsMultiFunc(int a,int b)
{
     return (a % b == 0);
}
void main(){
     int ari[]={1,2,3,4,5,6,7,8,9,10};
     vector<int> vi(&ari[0],&ari[10]);
     vector<int>::iterator it;
     for (it=vi.begin();;it++) {
          it=find_if(it, vi.end(), bind2nd(ptr_fun(IsMultiFunc),3));
          if (it==vi.end()) break;
          cout << *it << "이(κ°€) μžˆλ‹€" << endl;
     }
}