답변:
const_iterator
지시하는 값을 변경할 수 없습니다 iterator
.
C ++의 모든 것과 마찬가지로 const
정기적 반복자를 사용해야하는 좋은 이유가없는 한 항상 선호하십시오 (즉 const
, 지정된 값을 변경 하지 않는다는 사실을 사용하고 싶습니다 ).
그들은 거의 자명해야합니다. 반복자가 T 유형의 요소를 가리키는 경우 const_iterator는 'const T'유형의 요소를 가리 킵니다.
기본적으로 포인터 유형과 같습니다.
T* // A non-const iterator to a non-const element. Corresponds to std::vector<T>::iterator
T* const // A const iterator to a non-const element. Corresponds to const std::vector<T>::iterator
const T* // A non-const iterator to a const element. Corresponds to std::vector<T>::const_iterator
const 반복자는 항상 같은 요소를 가리 키므로 반복자 자체 는 const입니다. 그러나 가리키는 요소는 const 일 필요는 없으므로 가리키는 요소를 변경할 수 있습니다. const_iterator는 const 요소를 가리키는 반복자이므로 반복자 자체를 업데이트 (예 : 증가 또는 감소) 할 수 있지만 가리키는 요소는 변경할 수 없습니다.
const iterater
과 (과) 의 미묘함을 설명해주었습니다 const_iterator
.
불행히도 STL 컨테이너의 많은 메소드 는 const_iterators 대신 반복자 를 매개 변수로 사용합니다. 따라서 const_iterator 가 있다면 "이 반복자가 가리키는 요소 앞에 요소를 삽입하십시오"라고 말할 수 없습니다 (이러한 것은 개념적으로 const 위반이 아니라고 생각합니다). 어쨌든 그것을 원한다면 std :: advance () 또는 boost :: next ()를 사용하여 비 const 반복자로 변환해야합니다 . 예 : boost :: next (container.begin (), std :: distance (container.begin (), the_const_iterator_we_want_to_unconst)) . 경우 컨테이너 A는 표준 : : 목록 , 그 호출에 대한 실행 시간이 될 것입니다 O (n)을 .
따라서 "논리적"인 곳에 const를 추가하는 보편적 인 규칙은 STL 컨테이너와 관련하여 덜 보편적입니다.
그러나 부스트 컨테이너는 const_iterator를 사용합니다 (예 : boost :: unordered_map :: erase ()). 부스트 컨테이너를 사용할 때 "const agressive"가 될 수 있습니다. 그건 그렇고, STL 컨테이너가 언제 고쳐질 지 아는 사람이 있습니까?
vector
및 의 경우 deque
하나의 요소를 삽입하면 기존의 모든 반복자가 무효화됩니다 const
. 그러나 나는 당신의 요점을 봅니다. 이러한 작업은 const
반복자가 아닌 컨테이너 기능 으로 보호됩니다 . 그리고 표준 컨테이너 인터페이스에 const-non-const 반복자 변환 함수가없는 이유가 궁금합니다.
int const * foo;
int * const foo;
와 int const * const foo;
세 자신의 방법으로 각각 유효하고 유용합니다. std::vector<int> const bar
두 번째 것과 동일해야하지만 불행히도 종종 세 번째와 같이 취급됩니다. 문제의 근본 원인은 벡터에서 std::vector<int const> bar;
와 같은 효과를 얻을 수있는 방법이 없다는 것을 말할 수 없다는 것 int const *foo;
입니다.
최소 실행 가능 예제
비 const 반복자를 사용하면 그들이 가리키는 것을 수정할 수 있습니다.
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);
Const 반복자는하지 않습니다 :
const std::vector<int> v{0};
std::vector<int>::const_iterator cit = v.begin();
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
상술 한 바와 같이 v.begin()
되어 const
과부하 및 반환하거나 iterator
또는 const_iterator
용기 변수 CONST 다움에 따라 :
const_iterator
팝업이 나타나는 일반적인 경우 this
는 const
메서드 내에서 사용될 때 입니다 .
class C {
public:
std::vector<int> v;
void f() const {
std::vector<int>::const_iterator it = this->v.begin();
}
void g(std::vector<int>::const_iterator& it) {}
};
const
하게 this
만드는, CONST this->v
CONST.
일반적으로로 잊어 버릴 수 auto
있지만 반복자를 전달하기 시작하면 메소드 서명에 대해 반복자를 생각해야합니다.
const 및 non-const와 마찬가지로 non-const에서 const로 쉽게 변환 할 수는 있지만 다른 방법은 아닙니다.
std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
// non-const to const.
std::vector<int>::const_iterator cit = it;
// Compile time error: cannot modify container with const_iterator.
//*cit = 1;
// Compile time error: no conversion from const to no-const.
//it = ci1;
사용할 것 : const int
vs와 유사 int
: const 반복자를 사용할 수있을 때마다 (컨테이너를 수정할 필요가없는 경우) constiterator를 선호하여 수정하지 않고 읽을 의도를 더 잘 문서화합니다.
이제 상수 반복자를 사용하지 않고 간단한 예제로 설명하겠습니다. 임의의 정수 컬렉션 "randomData"가 있다고 가정하겠습니다.
for(vector<int>::iterator i = randomData.begin() ; i != randomData.end() ; ++i)*i = 0;
for(vector<int>::const_iterator i = randomData.begin() ; i!= randomData.end() ; ++i)cout << *i;
컬렉션 내에서 데이터 쓰기 / 편집을 위해 볼 수 있듯이 일반 반복자가 사용되지만 읽기 목적으로 상수 반복기가 사용되었습니다. 첫 번째 for 루프에서 상수 반복자를 사용하려고하면 오류가 발생합니다. 일반적으로 상수 반복자를 사용하여 콜렉션 내부의 데이터를 읽습니다.