STL

  1. 컨테이너 라이브러리에는 데이터를 저장하고 관리하는데 쓸수있는 컨테이너가 정의되어 있음.
  2. 반복자 라이브러리에는 반복자가 정의되어 있으며, 반복자는 포인터처럼 동작하는 객체로 컨테이너에 있는 객체의 순차열을 참조할때 사용
  3. 알고리즘 라이브러리에는 컨테이너에 저장된 원소에 적용할수 있는 알고리즘이 폭넓게 정의되어 있다.
  4. 수치 라이브러리에는 숫자와 관련된 기능이 폭넓게 정의되어 있으며, 원소에 수치 처리 기능이 있다.

템플릿

함수나 클래스를 매개변수로 작성한 명세.
매개변수화 타입 별칭으로 템플릿을 정의할수도 있다.

컨테이너

STL의 기능 대부분은 컨테이너와 관련되어 있다. STL의 근본이라고도 할수 있음.
컨테이너는 객체를 일정한 방식으로 저장하고 조직화하는 객체를 말한다.

  • 순차 컨테이너는 객체들을 선형으로 저장하고, 반드시 연속으로 저장하지는 않는다.
  • 연관 컨테이너는 객체들을 연관된 키와 함께 저장한다.
  • 컨테이너 어댑터는 순차 컨테이너나 연관 컨테이너에 저장된 데이터에 접근하는 다른방법을 제공하는 어댑터 클래스 템플릿을 말한다.
  • 기본적으로 T 객체를 컨테이너에 저장하려면 조건이 있는데, 기본생성자, 복사생성자, 소멸자, 할당연산자가 필요하다.

객체들이 RValue가 아니면 모든 STL 컨테이너는 객체를 저장할때 복사본을 저장하고,
STL에서 이동 생성자와 이동 할당 연산자가 반드시 noexcept로 지정되어야 된다.
컨테이너는 객체들을 힙에 저장하고 객체가 차지하는 공간도 자동으로 관리한다. 할당자 std::allocator<T> 담당한다.

반복자

포인터와 비슷하게 동작하는 클래스 템플릿 타입의 객체
반복자를 사용하면, 컨테이너에 있는 원소들에 접근하면서 일정한 방식으로 원소들을 처리할수 있다.

반복자 카테고리

  1. 읽기 반복자
    *iter을 지원한다.
  2. 출력 반복자
    *iter = new_value을 지원한다.
  3. 순방향 반복자
  4. 양방향 반복자
  5. 랜덤 엑세스 반복자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <numeric>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
double data[]{ 2.5, 4.5, 6.5, 5.5, 8.5 };
cout << "배열 원소들:\n";
for (auto iter = begin(data); iter != end(data); ++iter) // begin, end가 배열 원소 나열하는 데 쓰일 반복자 반환하는데 쓰이고 있음.
cout << *iter << " "; // *iter 반복자를 역참조해서 참조에 의한 값에 접근한다.

auto total = accumulate(begin(data), end(data), 0.0); // 함수 인수로 begin과 end가 사용됨 & accumulate 함수는 operator+()가 지원되어야 된다.
cout << "배열 원소의 합계 : " << total << endl;

return 0;
}

스트림 반복자

스트림과 소스 또는 스트림과 타깃 사이에 데이터를 텍스트 모드로 전송할수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <numeric>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
cout << "값은 공백으로 구분해서 입력. 종료하려면 Ctrl + Z" << endl;

cout << "\n입력한 값의 합은 "
<< accumulate(istream_iterator<double>(std::cin), istream_iterator<double>(), 0.0) // istream_iterator<double>() 끝 스트림 반복자,
<< endl;

return 0;
}

알고리즘

알고리즘은 데이터 원소들을 반복자로 접근하기 때문에 알고리즘은 데이터가 저장되는 위치에 관여하지않는다.

알고리즘 분류

  1. 변경불가 순차열 연산, 순차열의 내용을 변경하지 못한다.
  2. 변경가능 순차열 연산, 순차열의 내용을 변경한다.
  3. 정렬, 병합과 관련된 알고리즘은 순차열의 순서를 변경한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>
using namespace std;
class Root
{
public:
double operator()(double x)
{
return sqrt(x);
}
};

int main()
{
double data[]{ 1.5, 2.5, 3.5, 4.5, 5.5 };

// transform(시작인자, 끝인자, 결과로 돌려줄 시작위치를 지정하는 반복자, 입력범위에 적용될 함수);

// 함수 객체 전달하기
// functor
Root root;
cout << "Squre Roots are : " << endl;
transform(begin(data), end(data), ostream_iterator<double>(cout, " "), root);

// 람다 표현식을 인수로 사용하기
cout << "\n\nCubes are : " << endl;
transform(begin(data), end(data), ostream_iterator<double>(cout, " "),
[](double x) { return x * x * x; });

// function<> 타입의 변수를 인수로 사용하기
function<double(double)> op{ [](double x) {return x * x; } };
cout << "\n\nSquares are : " << endl;
transform(begin(data), end(data), ostream_iterator<double>(cout, " "), op);

// 다른 람다 표현식을 호출하는 람다 표현식을 인수로 사용하기
cout << "\n\n4th Power are : " << endl;
transform(begin(data), end(data), ostream_iterator<double>(cout, " "),
[&op](double x) {return op(x) * op(x); });

cout << endl;
}

문제풀이

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

#include <iostream>
#include <algorithm>
#include <iterator>
#include <functional>
#include <string>
using namespace std;

int main()
{
string strArr[]{
"Example to Zero",
"Example to One",
"Example to Two",
"Example to Three",
"Example to Four",
"Example to Five"
};

// 반복자를 사용해 배열의 내용을 한줄에 하나씩 출력
for (auto iter : strArr)
{
cout << iter << endl;
}

cout << endl << endl;
// transform을 사용하여 단어의 모든 소문자를 *로 대체하고, 표준 출력 스트림으로 한줄에 하나씩 출력
for (string iter : strArr)
{
transform(begin(iter), end(iter), ostream_iterator<char>(cout, ""),
[](char a)
{
if (a >= 97 && a <= 122)
return '*';

return a;
});

cout << endl;
}

cout << "Test Version \n";
transform(begin(strArr), end(strArr), ostream_iterator<string>(cout, "\n"),
[](string b)
{
for (auto& i : b)
{
if (i >= 97 && i <= 122)
i = '*';
}
return b;
});

// transform을 사용하여 단어의 모든 문자를 대문자로 바꾸는 프로그램 작성
for (auto iter : strArr)
{
transform(begin(iter), end(iter), ostream_iterator<char>(cout, ""), [](char a) { return static_cast<char>(::toupper(a)); });

cout << endl;
}

cout << "Test Version \n";
transform(begin(strArr), end(strArr), ostream_iterator<string>(cout, "\n"),
[](string b)
{
for (auto& i : b)
{
i = static_cast<char>(::toupper(i));
}
return b;
});

return 0;
}