일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 메타테이블
- implicit conversion
- Effective c++
- effective stl
- exception
- Smart Pointer
- 참조자
- 언리얼
- 영화 리뷰
- resource management class
- 암시적 변환
- 다형성
- 영화
- 반복자
- reference
- 스마트 포인터
- 상속
- 오블완
- 루아
- 예외
- c++
- lua
- operator new
- virtual function
- Vector
- 비교 함수 객체
- more effective c++
- 티스토리챌린지
- UE4
- 게임
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 37. 범위 요약(summarize) 본문
728x90
항목 37. 범위 내의 데이터 값을 요약하거나 더하는 데에는 accumulate나 for_each를 사용하자
범위 요약(summarize)
- 예를 들자면
- 컨테이너 string 요소들의 길이의 총합을 구한다.
- 주어진 범위의 숫자들의 곱을 구한다.
- 좌표 등 2차원 이상의 값들의 평균을 구한다.
- <numeric> 헤더에 있는 수치 알고리즘인 accumulate을 사용하자.
accumulate
- accumulate의 첫 번째 형태
- 두 개의 반복자와 초기값을 인자로 받는다.
- 범위 내의 값의 합 + 초기 값을 반환한다.
list<double> ld;
...
double sum = accumulate(ld.begin(), ld.end(), 0.0);
// 0.0을 초기값으로 주었기에, 합을 double로 하여 정상값이 리턴된다.
double sum = accumulate(ld.begin(), ld.end(), 0);
// 0을 초기값으로 주면, 합을 int로 하므로 원하는 값이 리턴되지 않는다.
- accumulate는 입력 반복자기만 하면 동작하므로 istream_iterators와 istreambuf_iterator(항목 29 참조)에 대해서도 적용 가능하다.
// cin으로 입력받은 값의 합들을 출력한다.
cout << "The sum of the ints on the standard input is "
<< accumulate(istream_iterator<int>(cin), istream_iterator<int>(), 0);
- accumulate의 두 번째 형태
- 기존의 형태에 추가로 요약용 함수를 인자로 받는다.
string::size_type stringLengthSum(string::size_type sumSoFar, const string& s)
{
return sumSoFar + s.size();
}
// 컨테이너::size_type은 size_t를 예쁘게 포장한 것이다.
set<string> ss;
...
// stringLengthSum 함수를 통한 요소값들 + 초기값을 리턴한다.
string::size_type lengthSum = accumulate(ss.begin(), ss.end(), 0, stringLengthSum);
- 두 번째 형태의 다양한 예시
// 범위 내의 수를 곱한다.
vector<float> vf;
...
float product = accumulate(vf.begin(), vf.end(), 1.0, multiplies<float>());
// 범위 안에 있는 point들의 평균 좌표를 찾는다.
struct Point
{
Point(double initX, double initY) : x(initX), y(initY) {}
double x, y;
};
class PointAverage
{
public:
PointAverage() : xSum(0), ySum(0), numPoints(0) {}
const Point operator()(const Point& avgSoFar, const Point& p)
{
// 내부값을 유지함으로써 사이드 이펙트가 발생한다.
// 보통의 컴파일러에서는 컴파일 에러가 발생한다.
++numPoints;
xSum += p.x;
ySum += p.y;
return Point(xSum / numPoints, ySum / numPoints);
}
private:
size_t numPoints;
double xSum;
double ySum;
};
list<Point> lp;
...
Point avg = accumulate(lp.begin(), lp.end(), Point(0, 0), PointAverage());
- 사이드 이펙트 문제를 해결하기 위해 for_each를 써보자.
for_each
- 이 알고리즘에 넘겨지는 함수는 자신이 처리할 단 하나의 요소만을 받아들이며,
- for_each의 수행을 마칠 때 이 함수의 사본을 반환한다.
- 즉, for_each에 넘겨지는, 반환되는 함수는 사이드 이펙트를 가져도 된다.
- accumulate와의 두 가지 차이
- accumulate에 비해 for_each라는 이름이 '요약한다'는 기능을 확실히 대변하지 않는다.
- accumulate는 요약 결과를 바로 반환하지만, for_each는 함수 객체를 반환하므로 이 객체에서 요약 정보를 뽑아내야 한다.
// 범위 안에 있는 point들의 평균 좌표를 찾는다.
struct Point
{
Point(double initX, double initY) : x(initX), y(initY) {}
double x, y;
};
class PointAverage
{
public:
PointAverage() : xSum(0), ySum(0), numPoints(0) {}
void operator()(const Point& p)
{
++numPoints;
xSum += p.x;
ySum += p.y;
}
Point result() const
{
return Point(xSum / numPoints, ySum / numPoints);
}
private:
size_t numPoints;
double xSum;
double ySum;
};
list<Point> lp;
...
Point avg = for_each(lp.begin(), lp.end(), PointAverage()).result();
728x90
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 39. predicate는 순수 함수일 것 (0) | 2025.01.07 |
---|---|
[Effective STL] 38. 함수 객체 클래스 값 전달(pass by value) 고려하기 (0) | 2025.01.03 |
[Effective STL] 36. copy_if (0) | 2024.12.26 |
[Effective STL] 35. 대소문자 구분하지 않는 법 (0) | 2024.12.24 |
[Effective STL] 34. 정렬된 범위에 동작하는 알고리즘 (0) | 2024.12.23 |
Comments