c++迭代器类型 - C++STL中的const_iterator和非const迭代器有什么区别?





c++迭代器实现 c++迭代器指针 (7)


const_iterator不允许你改变它们指向的值,常规iterator就是这样做的。

和C ++中的所有东西一样,除非有充分理由使用常规迭代器(即,您想使用它们不是const来更改指向值),否则始终更喜欢const

const_iteratoriterator之间有什么区别,你会在哪里使用另一个?




(正如其他人所说的)const_iterator不允许你修改它指向的元素,这在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元素的迭代器,因此当迭代器本身可以更新时(例如递增或递减),它指向的元素不能被更改。




最小的例子

非常量迭代器允许您修改它们指向的内容:

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重载,并根据容器变量的常量返回iteratorconst_iterator

const_iterator弹出的常见情况是在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来忘记它,但是如果你开始传递这些迭代器,你需要考虑方法签名。

与常量和非常量类似,您可以轻松地从非常量转换为常量,但不能以其他方式进行转换:

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 iterator,以更好地记录你的阅读意图而不用修改。




尽可能使用const_iterator ,当你没有其他选择时使用迭代器




不幸的是,很多STL容器的方法都是以迭代器而不是const_iterators作为参数。 所以如果你有一个const_iterator ,你不能说“在这个迭代器指向的元素之前插入一个元素”(在我看来,这样的事情在概念上并不是一个常量违反)。 如果你想这样做,你必须使用std :: advance()boost :: next()将其转换为非const迭代器。 例如。 boost :: next(container.begin(),std :: distance(container.begin(),the_const_iterator_we_want_to_unconst)) 。 如果容器std :: list ,那么该调用的运行时间将是O(n)

因此,在STL容器中,添加const的通用规则在“逻辑”的位置添加是不太普遍的。

但是,boost容器需要const_iterators(例如boost :: unordered_map :: erase())。 所以当你使用boost容器时,你可以是“不变的”。 顺便说一下,有谁知道是否或何时STL容器将被修复?




常量将作为字面值编译到使用者中,而静态字符串将用作所定义值的引用。

作为练习,尝试创建外部库并在控制台应用程序中使用它,然后更改库中的值并重新编译它(不重新编译使用者程序),将DLL放入目录并手动运行EXE,您应该找到该常量字符串不会更改。





c++ stl iterator const