그렇다. 메모리 낭비가 있는 것이다. for루프가 끝날때에는 중복되는 두개의 벡터가 존재하는 것이다. 그래서 우리가 쓸 방법은 만약 f면 fail에 추가하고, f 아니면 그 자리에서 지우는 것이다. 반갑게도 이런 기능이 있다. 근데 졸라 느리다. 입력 데이터의 양이 커질수록 성능 저하는 급격하다. 벡터에서는 중간에 하나를 지우면, 메모리를 통째로 다시 할당하고, 지워주는 짓을 해야한다. O(n*n)의 시간이 필요한것으로 알고 있다. 벡터는 임의 접근이 가능한 대신, 중간 삽입이나 중간 삭제의 퍼포먼스를 포기한 것이다. 이제부터 여러가지 방법을 살펴볼 것이다.
먼저 느리지만, 직관적인 방법부터 살펴보자.
~cpp
vector<Student_info> extract_fails(vector<Student_info>& students)
{
vector<Student_info> fail;
vector<Student_info>::size_type i = 0
while(i != students.size()) {
if(fgrade(students[i])) {
fail.push_back(students[i]);
students.erase(students.begin() + i);
} else
++i;
}
return fail;
}
- 왜 students.erase(studentsi) 하지 않는가? 모든 컨테이너에 일관성을 제공하기 위해서라고 한다. 바로 반복자라 불리우는 것을 이용해, (포인터보다 반복자가 먼저 나오네요.) 동일한 방법으로 제어를 할수 있는 것이다.
- 그림 보면 알겠지만, 복사 겁나게 해댄다. 하나 지울때마다 그 뒤에 있는걸 다 복사하는 것이다. 만약에 모두 fail이라면? 끔찍하다.
- 또한, 지워줌으로써 컨테이너의 사이즈가 변한다. 즉 모든 학생을 다 검사하지 못할수도 있다. 그래서 다음과 같이 바꿔주어야 한다.
~cpp
vector<Student_info> extract_fails(vector<Student_info>& students)
{
vector<Student_info> fail;
vector<Student_info>::size_type i = 0;
vector<Student_info>::size_type size = students.size();
while(i != size) {
if(fgrade(students[i])) {
fail.push_back(students[i]);
students.erase(students.begin() + i);
} else
++i;
}
return fail;
}