C ++ STL에서 const_iterator와 non-const 반복자의 차이점은 무엇입니까? an 의

a const_iterator와 an 의 차이점은 무엇 iterator이며 어디에서 다른 것을 사용합니까?



답변

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 요소를 가리키는 반복자이므로 반복자 자체를 업데이트 (예 : 증가 또는 감소) 할 수 있지만 가리키는 요소는 변경할 수 없습니다.


답변

불행히도 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 컨테이너가 언제 고쳐질 지 아는 사람이 있습니까?


답변

가능하면 const_iterator를 사용하고 다른 선택이 없을 때는 iterator 를 사용하십시오 .


답변

최소 실행 가능 예제

비 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팝업이 나타나는 일반적인 경우 thisconst메서드 내에서 사용될 때 입니다 .

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->vCONST.

일반적으로로 잊어 버릴 수 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 intvs와 유사 int: const 반복자를 사용할 수있을 때마다 (컨테이너를 수정할 필요가없는 경우) constiterator를 선호하여 수정하지 않고 읽을 의도를 더 잘 문서화합니다.


답변

(다른 사람들이 말했듯이) const_iterator를 사용하면 가리키는 요소를 수정할 수 없으며 const 클래스 메서드 내에서 유용합니다. 또한 의도를 표현할 수 있습니다.


답변

이제 상수 반복자를 사용하지 않고 간단한 예제로 설명하겠습니다. 임의의 정수 컬렉션 “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 루프에서 상수 반복자를 사용하려고하면 오류가 발생합니다. 일반적으로 상수 반복자를 사용하여 콜렉션 내부의 데이터를 읽습니다.