iterator : 정방향 iterator
reverse_iterator : 역방향 iterator
const_iterator : const형 정방향 iterator
const_reverse_iterator : const형 역방향 iterator
for(type element : container)
{
...
}
custom container를 사용할 경우 iterator처럼 작동하는 값을 반환하는 begin, end가 구현되어 있어야 사용 가능
find, compare 등 algorithm을 사용할 때 만약 container가 pointer를 담고 있다면 pointer 주소값을 비교하므로 _if 접미사가 붙은 함수와 predicate를 함께 사용해야 함
erase, clear 등 container의 element를 지우는 함수를 사용할 경우 delete를 수행한 후 삭제해야 메모리 누수가 발생하지 않음 -> RAII(pointer객체는 container가 생성하지 않았음)
for (auto iter = v.begin(); iter != v.end(); ++iter)
{
v.erase(iter);
}
erase함수의 반환 값은 삭제된 element다음 값을 가리킴
iter를 통해 erase할 경우 iterator는 다음 element를 가리킴
다만, 위와 같이 이동할 경우 nullptr exception이 발생
int main
{
vector<int> v;
v.reserve(2);
vector<int> v1(2);
vector<int> v2;
v2.resize(2);
}
생성자, resize를 통해 메모리를 확보할 경우 초기화되어 생성, 할당이 완료 됨
reserve를 통해 메모리를 확보할 경우 할당되지는 않음
reserve에 push_back할 경우 0번 index부터 값 할당
크고 많은 객체를 container에 보관할 경우 reserve를 통해 재할당 비용을 낮출 수 있음
container_constructor(count, value)
와 같은 역할
container_constructor(other_container_iterator, other_container_iterator)
를 통해 범위를 지정할 수 있음
container에서 direct하게 객체를 생성할 수 있음
불필요한 복사, 이동을 수행하지 않음
만약, 메모리를 미리 확보하지 않았다면 emplace를 수행하더라도 재할당으로 인해 효율이 떨어질 수 있음
이곳에서는 push_back도 emplace_back과 마찬가지로 컴파일러에서 최적화가 수행되어 불필요한 copy, move가 수행되지 않는다고 했지만, 실험결과 여전히 copy, move가 수행 됨
int main()
{
vector<Test> v;
v.reserve(10);
v.push_back(1);
v.push_back(Test(1));
v.emplace_back(1);
}
int main()
{
vector<Test*> v1;
v1.push_back(new Test(1));
v1.emplace_back(new Test(1));
}
emplace(new)를 수행해도 복사, 이동이 수행되지 않음.(완벽한 전달)
int main()
{
std::vector<std::vector<int>> vec;
vec.push_back(10); //compile error
vec.emplace_back(10); //공간이 10개인 vector가 생성되어 vec에 들어감
}
emplace의 경우 어떤 생성자가 호출되는지 명확하지 않음
int main
{
for (auto iter = v.begin(); iter != v.end(); ++iter)
{
v.emplace(iter, 1); //nullptr exception
}
}
emplace나 insert나 재할당 받은 메모리 공간의 크기에 따라 iterator를 무효화시키기도 하는데, 이 조건을 엄밀하게 제어할 수 없으므로 그냥 한번만 사용하자
밧줄을 잇다, 붙이다의 뜻
다른 container의 값을 옮기는 함수
중복 허용 여부
기본적으로 오름차순 정렬
표준이 결정된 것은 아니지만 GCC의 경우 BST(RB Tree)로 구현됨
Hash를 통해 구현됨
중복 허용 여부
기본적으로 오름차순 정렬
표준이 결정된 것은 아니지만 GCC의 경우 BST(RB Tree)로 구현됨
전반적으로 algorithm.h의 함수들에는 사용할 수 없는것으로 보임
Hash를 통해 구현됨
algorithm이 지원하는 함수보다 STL에서 자체적으로 지원하는 함수가 더 빠름
container의 element를 수정하는지 여부를 중요하게 확인해야 함
bool comp(int i) { return i == 5; }
class compClass
{
public:
bool operator()(int i) { return i == 5; }
};
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
auto iter = count_if(v.begin(), v.end(), comp);
auto iter1 = count_if(v.begin(), v.end(), compClass{});
return 0;
}
predicate를 요구하는 객체는 함수, 객체 상관 없음
Lambda함수도 가능
sort(SortedContainer.begin(), SortedContainer.end(), CompClass());
sort(SortedContainer.begin(), SortedContainer.end(), CompFunc);
범위 지정
Container<Template>::iterator iter2 = find_if(Container.begin(), Container.end(), CompClass());
Container<Template>::iterator iter2 = find_if(Container.begin(), Container.end(), CompFunc);
copy(CopiedContainer.begin(), CopiedContainer.end(), std::back_inserter(CopyContainer));
back_inserter가 필요
또는 iterator를 통한 copy가 가능한 듯
generate(Container.begin(), Container.end(), FuncObject);
특정 범위의 원소를 함수객체의 반환값으로 채움
merge(Container1BeginIteartor, Container1EndIteartor, Container2BeginIteartor, Container2EndIterator, std::back_inserter(ResultContainer));
정렬된 두 Container를 Merge정렬하면서 ResultContainer에 복사
transform(BeginIterator, EndIterator, back_inserter(ResultContainer), FunctionObject);
transform(Container1BeginIterator, Container1EndIterator, Container2BeginIterator, back_inserter(ResultContainer), FunctionObject);
Container의 각 Element를 수정하여 ResultContainer에 저장
std::transform(ContainerBeginIterator, ContainerEndIterator, back_inserter(SameContainer), FunctionObject);
이 경우 무한루프가 발생하지는 않지만, Garbage값이 입력
class Class
{
public:
returnType operator()(type param, ...) { ... }
};
연산자 재정의를 지원하는 모든 객체는 함수 객체
functional.h에 존재하는 객체
이와 별개로
function<type>
형태의 Callable을 모두 담을 수 있는 객체도 있음
위와 같은 경우 FunctionObject를 전달하기 위해 새롭게 함수를 정의하거나 Class, Struct를 정의하는 것 보단 간편하게 함수 객체를 생성할 수 있음
ReturnType functionName(int count, ...) { ... }
ReturnType functionName(type ...) { ... }
#include <cstdarg>
#define va_start
#define va_arg
#define va_end
#define va_copy
위 define을 이용해 인자에 접근
template<typename ... Types>
ReturnType functionName(Types ... args) { ... }