10장. 템플릿과 표준 템플릿 라이브러리 (STL)
함수 중복의 약점 - 중복 함수의 코드 중복
#include <iostream>
using namespace std;
void myswap(int& a, int& b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
void myswap(double& a, double& b) {
double tmp;
tmp = a;
a = b;
b = tmp;
}
// 동일한 코드 중복 작성
// 두 함수는 매개변수만 다르고 나머지 코드는 동일함
int main() {
int a = 4, b = 5;
myswap(a, b);
cout << a << '\t' << b << endl;
double c = 0.3, d = 12.5;
myswap(c, d);
cout << c << '\t' << d << endl;
}
C++
복사
일반화와 템플릿
제네릭 (generic) 또는 일반화
•
함수나 클래스를 일반화시키고, 매개변수 타입을 지정하여
•
틀에서 찍어내듯이
•
함수나 클래스 코드르 생산하는 기법
템플릿
•
함수나 클래스를 일반화하는 C++ 도구
•
template 키워드로 함수나 클래스 선언
◦
변수나 매개변수의 타입만 다르고, 코드 부분이 동일한 함수를 일반화시킴
•
제네릭 타입 - 일반화를 위한 데이터 타입
템플릿 선언
template <class T> 또는
template <typename T>
// 3개의 제네릭 타입을 가진 템플릿 선언
template <class T1, class T2, class T3>
C++
복사
template <class T> // 제네릭 타입 T 선언
void myswap(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
C++
복사
구체화 (specialization)
•
템플릿의 제네릭 타입에, 구체적인 타입을 지정
◦
템플릿 함수로부터 구체화된 함수의 소스코드 생성
template <class T> // 제네릭 타입 T 선언
void myswap(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
C++
복사
이 코드를
void myswap(int& a, int& b) {
int tmp;
tmp = a;
a = b;
b = tmp;
}
C++
복사
로 구체화
제네릭 myswap() 함수 만들기
#include <iostream>
using namespace std;
class Circle {
int radius;
public:
Circle(int radius = 1) { this->radius = radius; }
int getRadius() { return radius; }
};
template <class T>
void myswap(T& a, T& b) {
T tmp;
tmp = a;
a = b;
b = tmp;
}
int main() {
int a = 4, b = 5;
myswap(a, b);
cout << "a = " << a << ", " << "b = " << b << endl;
double c = 0.3, d = 12.5;
myswap(c, d);
cout << "c = " << c << ", " << "d = " << d << endl;
Circle donut(5), pizza(20);
myswap(donut, pizza);
cout << "donut 반지름 = " << donut.getRadius() << ", ";
cout << "pizza 반지름 = " << pizza.getRadius() << endl;
}
C++
복사
구체화 오류
•
제네릭 타입에 구체적인 타입 지정 시 주의
template <class T> void myswap(T& a, T& b)
C++
복사
→ 두 매개변수 a, b의 제네릭 타입 동일
int s = 4;
double t = 5;
myswap(s, t);
C++
복사
→ 두 개의 매개변수의 타입이 서로 다름
→ 컴파일 오류, 템플릿으로부터 myswap(int &, double &) 함수를 구체화할 수 없다
템플릿 장점과 제네릭 프로그래밍
템플릿 장점
•
함수 코드의 재사용
◦
높은 SW의 생산성과 유용성
템플릿 단점
•
포팅에 취약
◦
컴파일러에 따라 지원하지 않을 수 있음
•
컴파일 오류 메시지 빈약, 디버깅에 많은 어려움
제네릭 프로그래밍 (generic programming)
•
일반화 프로그래밍
•
제네릭 함수나 제네릭 클래스를 활용하는 프로그래밍 기법
•
C++ 에서 STL (Standard Template Library) 제공, 활용
•
보편화 추세 - JAVS, C# 등 많은 언어에서 활용
예제 10-2) 큰 값을 리턴하는 bigger() 함수 만들기 연습
#include <iostream>
using namespace std;
template <class T>
T bigger(T a, T b) {
if (a > b)
return a;
else
return b;
}
int main() {
int a = 20, b = 50;
char c = 'a', d = 'z';
cout << "bigger(20, 50)의 결과는 " << bigger(a, b) << endl;
cout << "bigger('a', 'z')의 결과는 " << bigger(c, d) << endl;
}
C++
복사
예제 10-3) 배열의 합을 구하여 리턴하는 제네릭 add() 함수 만들기 연습
#include <iostream>
using namespace std;
template <class T>
T add(T data [], int n) {
T sum = 0;
for (int i = 0; i < n; i++) {
sum += data[i];
}
return sum;
}
int main() {
int x[] = {1, 2, 3, 4, 5};
double d[] = {1.2, 2.3, 3.4, 4.5, 5.6, 6.7};
cout << "sum of x[] = " << add(x, 5) << endl;
cout << "sum of d[] = " << add(d, 6) << endl;
}
C++
복사
예제 10-4) 배열을 복사하는 제네릭 함수 mcopy() 함수 만들기 연습
#include <iostream>
using namespace std;
// 두 개의 제네릭 타입 T1, T2를 가지는 copy() 의 템플릿
template <class T1, class T2>
void mcopy(T1 src [], T2 dest [], int n) {
for (int i = 0; i < n; i++)
dest[i] = (T2)src[i];
// T1 타입의 값을 T2 타입으로 변환한다
}
int main() {
int x[] = {1, 2, 3, 4, 5};
double d[5];
char c[5] = {'H', 'e', 'l', 'l', 'o'}, e[5];
mcopy(x, d, 5); // int x[]의 원소 5개를 double d[] 에 복사
mcopy(c, e, 5); // char c[]의 원소 5개를 char e[] 에 복사
for (int i = 0; i < 5; i++)
cout << d[i] << ' '; // d[] 출력
cout << endl;
for (int i = 0; i < 5; i++)
cout << e[i] << ' '; // e[] 출력
cout << endl;
}
C++
복사
배열을 출력하는 print() 템플릿 함수의 문제점
#include <iostream>
using namespace std;
template <class T>
void print(T array [], int n) {
for (int i = 0; i < n; i++)
cout << array[i] << '\t';
// T가 char로 구체화되는 경우, 정수 1, 2, 3, 4, 5에 대한 그래픽 문자 출력
// char로 구체화되면, 숫자대신 문자가 출력되는 문제 발생
cout << endl;
}
int main() {
int x[] = {1, 2, 3, 4, 5};
double d[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
print(x, 5);
// print() 템플릿의 T가 int 타입으로 구체화
print(d, 5);
char c[5] = {1, 2, 3, 4, 5};
print(c, 5);
// print() 템플릿의 T가 char 타입으로 구체화
}
C++
복사
예제 10-5) 템플릿 함수보다 중복 함수가 우선
#include <iostream>
using namespace std;
template <class T>
void print(T array [], int n) {
for (int i = 0; i < n; i++)
cout << array[i] << '\t';
cout << endl;
}
// 템플릿 함수와 중복된 print() 함수
void print(char array [], int n) {
// char 배열을 출력하기 위한 함수 중복
for (int i = 0; i < n; i++)
cout << (int)array[i] << '\t';
// array[i]를 int 타입으로 변환하여 정수 출력
cout << endl;
}
int main() {
int x[] = {1, 2, 3, 4, 5};
double d[5] = {1.1, 2.2, 3.3, 4.4, 5.5};
print(x, 5);
print(d, 5);
// 템플릿 print() 함수로부터 구체화
char c[5] = {1, 2, 3, 4, 5};
print(c, 5);
// 중복된 print() 함수가 우선 바인딩
}
C++
복사
제네릭 클래스 만들기
제네릭 클래스 선언
template <class T>
class MyStack {
int tos;
T data[100]; // T 타입의 배열
public:
MyStack();
void push(T element);
T pop();
};
C++
복사
제네릭 클래스 구현
template <class T>
void MyStack<T>::push(T element) {
...
}
tmeplate <class T> T MyStack<T>::pop() {
...
}
C++
복사
클래스 구체화 및 객체 활용
MyStack<int> iStack; // int 타입을 다루는 스택 객체 생성
MyStack<double> dStack; // double 타입을 다루는 스택 객체 생성
iStack.push(3);
int n = iStack.pop();
dStack.push(3.5);
double d = dStack.pop();
C++
복사
예제 10-6) 제네릭 스택 클래스 만들기
#include <iostream>
using namespace std;
template <class T>
class MyStack {
int tos;
T data [100];
// T 타입의 배열, 스택의 크기는 100
public:
MyStack();
void push(T element); // element를 data [] 배열에 삽입
T pop();
};
template <class T>
MyStack <T>::MyStack() { // 생성자
tos = -1; // 스택은 비어 있음
}
template <class T>
void MyStack<T>::push(T element) {
if (tos == 99) {
cout << "stack full";
return;
}
tos++;
data[tos] = element;
}
template <class T>
T MyStack<T>::pop() {
T retData;
if (tos == -1) {
cout << "stack empty";
return 0; // 오류 표시
}
retData = data[tos--];
return retData;
}
int main() {
MyStack<int> iStack; // int만 저장하는 스택
iStack.push(3);
cout << iStack.pop() << endl;
MyStack<double> dStack; // double만 저장하는 스택
dStack.push(3.5);
cout << dStack.pop() << endl;
MyStack<char> *p = new MyStack<char>(); // char만 저장하는 스택
p->push('a');
cout << p->pop() << endl;
delete p;
}
C++
복사
예제 10-7) 제네릭 스택의 제네릭 타입을 포인터나 클래스로 구체화하는 예
#include <iostream>
#include <string>
using namespace std;
class Point {
int x, y;
public:
Point(int x = 0, int y = 0) { this->x = x; this->y = y; }
void show() { cout << "(" << x << ', ' << y << ")" << endl; }
};
int main() {
MyStack<int *> ipStack; // int* 만을 저장하는 스택
int *p = new int [3];
for (int i = 0; i < 3; i++) p[i] = i*10; // 0, 10, 20으로 초기화
ipStack.push(p); // 포인터 푸시
int *q = ipStack.pop(); // 포인터 팝
for (int i = 0; i < 3; i++) cout << q[i] << ' ';
cout << endl;
delete [] p;
MyStack<Point> pointStack; // Point 객체 저장 스택
Point a(2, 3) b;
pointStack.push(a); // Point 객체 a 푸시, 복사되어 저장
b = pointStack.pop(); // Point 객체 팝
b.show();
MyStack<Point*> pStack; // Point* 포인터 스택
pStack.push(new Point(10, 20)); // Point 객체 푸시
Point* pPoint = pStack.pop(); // Point 객체의 포인터 팝
pPoint->show();
MyStack<string> stringStack; // 문자열만 저장하는 스택
string s = "c++";
stringStack.push(s);
stringStack.push("java");
cout << stringStack.pop() << ' ';
cout << stringStack.pop() << endl;
}
C++
복사
예제 10-8) 두 개의 제네릭 타입을 가진 클래스 만들기
#include <iostream>
using namespace std;
template <class T1, class T2> // 두 개의 제네릭 타입 선언
class GClass {
T1 data1;
T2 data2;
public:
GClass();
void set(T1 a, T2 b);
void get(T1 &a, T2 &b);
// data1을 a에, data2를 b에 리턴하는 함수
};
template <class T1, class T2>
GClass<T1, T2>::GClass() {
data1 = 0; data2 = 0;
}
template <class T1, class T2>
void GClass<T1, T2>::set(T1 a, T2 b) {
data1 = a; data2 = b;
}
template <class T1, class T2>
void GClass<T1, T2>::get(T1 & a, T2 & b) {
a = data1; b = data2;
}
int main() {
int a;
double b;
GClass<int, double> x;
x.set(2, 0.5);
x.get(a, b);
cout << "a=" << a << '\t' << "b=" << b << endl;
char c;
float d;
GClass<char, float> y;
y.set('m', 12.5);
y.get(c, d);
cout << "c=" << c << '\t' << "d=" << d << endl;
}
C++
복사
C++ 표준 템플릿 라이브러리, STL
STL (Standard Template Library)
•
표준 템플릿 라이브러리
•
많은 제네릭 클래스와 제네릭 함수 포함
STL의 구성
•
컨테이너 - 템플릿 클래스
◦
데이터를 담아두는 자료구조를 표현한 클래스
◦
리스트, 큐, 스택, 맵, 셋, 벡터
•
iterator - 컨테이너 원소에 대한 포인터
◦
컨테이너의 원소들을 순회하면서, 접근하기 위해 만들어진 컨테이너 원소에 대한 포인터
•
알고리즘 - 템플릿 함수
◦
컨테이너 원소에 대한 복사, 검색, 삭제, 정렬 등의 기능을 구현한 템플릿 함수
◦
컨테이너의 멤버 함수 아님
STL 컨테이너의 종류
컨테이너 클래스 | 설명 | 헤더 파일 |
vector | 가변 크기의 배열을 일반화한 클래스 | <vector> |
deque | 앞 뒤 모두 입력 가능한 큐 클래스 | <deque> |
list | 빠른 삽입/삭제 가능한 리스트 클래스 | <list> |
set | 정렬된 순서로 값을 저장하는 집합 클래스, 값은 유일 | <set> |
map | (key, value) 쌍을 저장하는 맵 클래스 | <map> |
stack | 스택을 일반화한 클래스 | <stack> |
queue | 큐를 일반화한 클래스 | <queue> |
STL iterator의 종류
iterator의 종류 | iterator에 ++ 연산 후 방향 | read/write |
iterator | 다음 원소로 전진 | read/write |
const_iterator | 다음 원소로 전진 | read |
reverse_iterator | 지난 원소로 후진 | read/write |
const_reverse_iterator | 지난 원소로 후진 | read |
STL 알고리즘 함수들
copy | merge | random | rotate |
equal | min | remove | search |
find | move | replace | sort |
max | partition | reverse | swap |
vector 컨테이너
•
가변 길이 배열을 구현한 제네릭 클래스 - 벡터의 길이에 대한 고민할 필요 없다!
•
원소의 저장, 삭제, 검색 등 다양한 멤버 함수 지원
•
벡터에 저장된 원소는 인덱스로 접근 가능 - 인덱스는 0부터 시작
멤버와 연산자 함수 | 설명 |
push_back (element) | 벡터의 마지막에 element 추가 |
at (int index) | index 위치의 원소에 대한 참조 리턴 |
begin () | 벡터의 첫 번째 원소에 대한 참조 리턴 |
end () | 벡터의 끝(마지막 원소 다음)을 가리키는 참조 리턴 |
empty () | 벡터가 비어 있으면 true 리턴 |
erase (iterator it) | 벡터에서 it가 가리키는 원소 삭제, 삭제 후 자동으로 벡터 조절 |
insert (iterator it, element) | 벡터 내 it 위치에 element 삽입 |
size() | 벡터에 들어있는 원소의 개수 리턴 |
operator[]() | 지정된 원소에 대한 참조 리턴 |
operator=() | 이 벡터를 다른 벡터에 치환(복사) |
vector 다루기 사례
// vector 생성
vector<int> v;
// 정수 원소 삽입
v.push_back(1);
v.push_back(2);
v.push_back(3);
// 원소 개수 s, 벡터 용량 c
int s = v.size();
int c = v.capacity();
// 원소 값 접근
v.at(2) = 5;
int n = v.at(1);
// 원소 값 접근
v[0] = 10;
int m = v[2];
C++
복사
예제 10-9) vector 컨테이너 활용하기
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v; // 정수만 삽입 가능한 벡터 생성
v.push_back(1);
v.push_back(2);
v.push_back(3);
for (int i = 0; i < v.size(); i++) // 벡터의 모든 원소 출력
cout << v[i] << " "; // v[i]는 벡터의 i번째 원소
cout << endl;
v[0] = 10; // 벡터의 첫 번째 원소를 10으로 변경
int n = v[2]; // n에 3 저장
v.at(2) = 5; // 벡터의 3번째 원소를 5로 변경
for (int i = 0; i < v.size(); i++)
cout << v[i] << " ";
cout << endl;
}
C++
복사
예제 10-10) 문자열을 저장하는 벡터 만들기 연습
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main() {
vector<string> sv; // 문자열 생성
string name;
cout << "이름을 5개 입력하라" << endl;
for (int i = 0; i < 5; i++) {
cout << i + 1 << ">>";
getline(cin, name);
sv.push_back(name);
}
name = sv.at(0); // 벡터의 첫 원소
for (int i = 1; i < sv.size(); i++) {
if (name < sv[i]) // sv[i]의 문자열이 name보다 사전에서 뒤에 나옴
name = sv[i]; // name을 sv[i]의 문자열로 변경
}
cout << "사전에서 가장 뒤에 나오는 이름은 " << name << endl;
}
C++
복사
iterator
•
반복자
•
컨테이너의 원소를 가리키는 포인터
•
iterator 변수 선언
◦
구체적인 컨테이너를 지정하여 반복자 변수 생성
vector<int>::iterator it;
it = v.begin();
C++
복사
→ it는 원소가 int 타입인 벡터의 원소에 대한 포인터
// 벡터 생성
vector<int> v;
for (int i = 1; i < 4; i++)
v.push_back(i);
// iteraotr 변수 선언 및 초기화
vector<int>::iterator it;
it = v.begin();
// iterator 증가
it++;
// 원소 읽기
int n = *it
// 원소 쓰기
n = n*2;
*it = n;
// 원소 삭제
it = v.erase(it);
// 끝으로 옮기기
it = v.end();
C++
복사
10-11) iterator를 사용하여 vector의 모든 원소에 2 곱하기
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
vector<int>::iterator it; // 벡터 v의 원소에 대한 포인터 it 선언
for (it = v.begin(); it != v.end(); it++) { // iterator를 이용하여 모든 원소 탐색
int n = *it; // it가 가리키는 원소 값 리턴
n = n*2;
*it = n; // it가 가리키는 원소에 값 쓰기
}
for (it = v.begin(); it != v.end(); it++) // 벡터 v의 모든 원소 출력
cout << *it << ' ';
cout << endl;
}
C++
복사
map 컨테이너
•
특징
◦
(’키', ‘값') 의 쌍을 원소로 저장하는 제네릭 컨테이너
▪
동일한 ‘키’를 가진 원소가 중복 저장되면 오류 발생
◦
‘키'로 ‘값' 검색
#include <map>
C++
복사
•
맵 컨테이너 생성 예
// 맵 생성
Map<string, string> dic;
// 원소 저장
dic.insert(mak_pair("love", "사랑"));
dic["love"] = "사랑";
// 원소 검색
string kor = dic["love"];
string kor = dic.at("love");
C++
복사
멤버와 연산자 함수 | 설명 |
insert (pair<> &element) | 맵에 ‘키’와 ‘값’으로 구성된 pair 객체 element 삽입 |
at (key_type& key) | 맵에서 ‘키’ 값에 해당하는 ‘값’ 리턴 |
begin () | 맵의 첫 번째 원소에 대한 참조 리턴 |
end () | 맵의 끝(마지막 원소 다음)을 가리키는 참조 리턴 |
empty () | 벡터가 비어 있으면 true 리턴 |
find(key_type& key) | 맵에서 ‘키’ 값에 해당하는 원소를 가리키는 iterator 리턴 |
erase (iterator it) | 맵에서 it가 가리키는 원소 삭제 |
size() | 맵에 들어있는 원소의 개수 리턴 |
operator[key_type& key]() | 맵에서 ‘키’ 값에 해당하는 원소를 찾아 ‘값’ 리턴 |
operator=() | 맵 치환(복사) |
예제 10-12) map으로 영한 사전 만들기
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
map<string, string> dic;
dic.insert(make_pair("love", "사랑"));
dic.insert(make_pair("apple", "사과"));
dic["cherry"] = "체리";
cout << "저장된 단어 개수 " << dic.size() << endl;
string eng;
while (true) {
cout << "찾고 싶은 단어>> ";
getline(cin, eng);
if (eng == "exit") break;
if (dic.find(eng) == dic.end()) // eng "키"를 끝까지 찾았는데 없다면
cout << "None" << endl;
else
cout << dic[eng] << endl;
}
cout << "exit" << endl;
}
C++
복사
STL 알고리즘 사용하기
알고리즘 함수
•
템플릿 함수
•
전역 함수
◦
STL 컨테이너 클래스의 멤버 함수가 아님
sort() 함수 사례
•
두 개의 매개변수
◦
첫번재 매개변수 : sorting을 시작한 원소의 주소
◦
두번째 매개변수 : sorting 범위의 마지막 원소 다음 주소
예제 10-13) sort() 함수를 이용한 vector sorting
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v;
cout << "5개의 정수를 입력하세요>> ";
for (int i = 0; i < 5; i++) {
int n;
cin >> n;
v.push_back(n);
// 키보드에서 읽은 정수를 벡터에 삽입
}
sort(v.begin(), v.end());
// v.begin()에서 v.end() 사이의 값을 오름차순으로 정렬
// sort() 함수의 실행 결과 벡터 v의 원소 순서가 변경됨
vector<int>::iterator it; // 벡터 내의 원소를 탐색하는 iterator 변수 선언
for (it = v.begin(); it != v.end(); it++)
cout << *it << ' ';
cout << endl;
}
C++
복사
auto를 이용하여 쉬운 변수 선언
c++ auto
•
기능
◦
컴파일러에게 변수 선언문에서 추론하여, 타입을 자동 선언하도록 지시
•
장점
◦
복잡한 변수 선언을 간소하게, 긴 타입 선언 시 오타 줄인다
auto pi = 3.14
auto n = 3;
auto *p = &n;
int n = 10;
int &ref = n;
auto ref2 = ref; // ref2는 int& 변수로 자동 선언
C++
복사
•
함수의 리턴 타입으로부터 추론하여, 변수 타입 선언
int square(int x) { return x * x; }
...
auto ret = square(3) // 변수 ret는 int 타입으로 추론
C++
복사
•
STL 템플릿에 활용
vector<int>::iterator it; // 벡터 내의 원소를 탐색하는 iterator 변수 선언
for (it = v.begin(); it != v.end(); it++)
cout << *it << ' ';
C++
복사
이거를
for (auto it = v.begin(); it != v.end(); it++)
cout << *it << endl;
C++
복사
이렇게 간단히 선언 가능
예제 10-14) auto 이용한 변수 선언
#include <iostream>
#include <vector>
using namespace std;
int square(int x) { return x * x; }
int main() {
auto c = 'a';
auto pi = 3.14;
auto ten = 10;
auto *p = &ten;
cout << c << " " << pi << " " << ten << " " << *p << endl;
auto ret = square(3);
cout << *p << " " << ret << endl;
vector<int> v = { 1, 2, 3, 4, 5 };
vector<int>::iterator it;
for (it = v.begin(); it != v.end(); it++)
cout << *it << " ";
cout << endl;
for (auto it = v.begin(); it != v.end(); it++)
cout << *it << " ";
}
C++
복사
람다 (lambda)
람다 대수와 람다식
•
람다 대수에서 람다식은 수학 함수를 단순하게 표현하는 기법
•
구성
◦
캡쳐 리스트
◦
매개변수 리스트
◦
리턴 타입
◦
함수 바디
[ ]( ) -> 리턴타입 { /* 함수코드 작성*/ };
[](int x, int y){cout << x+y;};
[](int x, int y)->int{return x + y;};
[](int x, int y){cout << x+y;}(2, 3);
C++
복사
#include <iostream>
using namespace std;
int main() {
[](int x, int y){cout << "합은 " << x+y;}(2, 3);
}
C++
복사
예제 10-16) auto로 람다식 다루기
#include <iostream>
#include <string>
using namespace std;
int main() {
auto love = [](string a, string b) {
cout << a << "보다" << b << "가 좋아" << endl;
};
love("돈", "너");
love("냉면", "만두");
}
C++
복사
예제 10-17) 반지름 r이 원의 면적으로 리턴하는 람다식 만들기
#include <iostream>
using namespace std;
int main() {
double pi = 3.14;
auto calc = [pi](int r) -> double { return pi*r*r; };
cout << "면적은 " << calc(3);
}
C++
복사
예제 10-18) 캡쳐 리스트에 참조 활용, 합을 외부에 저장하는 람다식 만들기
#include <iostream>
using namespace std;
int main() {
int sum = 0;
[&sum](int x, int y) { sum = x + y; }(2, 3);
// 합 5를 지역변수 sum에 저장
cout << "합은 " << sum;
}
C++
복사
예제 10-19) STL for_each() 함수를 이용하여 벡터의 모든 원소 출력
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void print(int n) {
cout << n << " ";
}
int main() {
vector<int> v = {1, 2, 3, 4, 5};
for_each(v.begin(), v.end(), print);
// for_each()는 벡터 v의 첫번째 원소부터 끝까지 검색하면서,
// 각 원소에 대해 print(int n) 호출, 매개변수 n에 각 원소 값 전달
}
C++
복사
예제 10-20) STL 함수 for-each() 와 람다식을 이요하여, 벡터의 모든 원소 출력
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = { 1, 2, 3, 4, 5 };
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
// for_each()는 벡터 v의 첫번째 원소부터 끝까지 검색하면서
// 각 원소에 대해 3번째 매개변수인 람다식 호출, 매개변수 n에 각 원소 값 전달
// 람다식 호출 -> 매개변수 n에는 벡터의 각 원소 전달
}
C++
복사