일반적으로 STL 컨테이너를 순회하며 작업할 때 이터레이터(iterator)를 많이 사용합니다. 그런데 const_iterator는 사용하는 프로그래머는 항상 사용하고, 사용하지 않는 프로그래머는 늘 일반 iterator만 사용합니다. 이번에 둘 간에 어떤 차이가 있는지, 그리고 성능 차이는 없는지 알아보겠습니다.
const_iterator와 iterator의 차이
const_iterator가 그냥 iterator와 다른 점은, const T* 포인터의 형태와 같이 const 값을 가리키는 반복자라는 것 밖에 없습니다. 즉, 이것을 역 참조했을 때 const T& 형태의 참조를 반환하게 됩니다. 이것은 const 지시어가 있는 변수이므로 역참조 된 값을 변경할 수 없도록 방지되는 효과가 있습니다. 값을 변경하려는 의도가 없는 경우에는 const 버전을 사용해서 실수를 방지할 수 있게 되는 것입니다.
단지 나의 실수뿐 아니라, 향후에 내 코드를 받아서 유지 보수하는 사람에게도 많은 도움이 됩니다. 예제 코드로 한번 살펴 보도로 하겠습니다.
std::vector에서 const_iterator와 iterator의 차이
우선 아래와 같이 선언된 int 형의 vector가 있습니다.
std::vector<int> integers{ 3, 4, 56, 6, 778 };
이때 일반 이터레이터를 사용해서 vector를 순회하는 코드는 아래와 같습니다.
for( std::vector<int>::iterator it = integers.begin(); it != integers.end(); ++it )
{
std::cout << *it << std::endl;
*it = 100;
}
*it을 통해 값 변경이 가능한 것을 알 수 있습니다. 다음은 const_iterator를 사용한 예제입니다.
for( std::vector<int>::const_iterator it = integers.begin(); it != integers.end(); ++it )
{
std::cout << *it << std::endl;
*it = 100; // 컴파일 에러 발생
}
동일한 코드이지만 *it에 값을 대입할고 하면 컴파일 에러가 발생합니다. const 변수에 값을 대입하는 것과 같은 행위이기 때문입니다.
std::list에서 const_iterator와 iterator의 차이
다음은 list 컨테이너를 사용한 예제입니다. 마찬가지로 const 버전의 이터레이터에서는 값 변경 시도 시 에러가 발생합니다.
list<int>::iterator it; // 일반 iterator
list<int>::const_iterator cit; // const 버전 iterator
it = a.begin();
cit = a.begin();
*it = *it + 1; // 역참조하여 값을 1 증가시키려는 동작. 성공함.
*cit = *cit + 1; // const 버전이기 때문에 값을 참조하는 것은 문제 없으나 대입하려고 할때 오류 발생.
iterator와 const_iterator의 성능 차이
일반적으로 둘 간에 성능 차이는 없다고 알려져 있습니다. 단지 const 키워드가 있어서 컴파일러가 미리 체크를 할 뿐이기 때문이죠. 하지만 성능 차이가 있다고 말하는 전문가들도 있습니다. 객체가 반복자 조작으로 변경되지 않을 것이라는 보장이 되므로, 컴파일러가 최적화를 할 수 있는 여지를 준다는 의견이죠. 하지만 이것도 COW(copy-on-write) 방식의 container에 한해서 효율적일 가능성이 있는 것이고, STLish(STL-ish) container는 그렇지 않을 가능성이 높다고 합니다.
'개발일기 > 설계와디자인' 카테고리의 다른 글
일론 머스크에게서 배우는 설계와 개발의 원칙들 (0) | 2022.02.27 |
---|---|
C++ 네임스페이스 사용 장점과 단점 (using namespace std) (0) | 2021.11.06 |
std::vector 와 std::array 중 어떤 것을 사용할지의 선택 기준 (0) | 2021.11.06 |
댓글