在 C + + STL 中 const _ iterator 和非 const 迭代器的区别是什么?

const_iteratoriterator的区别是什么? 你会在哪里使用它们?

112961 次浏览

const_iterator不允许您更改它们指向的值,常规 iterator允许。

与 C + + 中的所有内容一样,总是更喜欢使用 const,除非有充分的理由使用常规迭代器(例如,您希望使用它们不是 const的事实来更改指向值)。

它们应该是不言而喻的。如果 iterator 指向 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 _ iterator,在别无选择时使用 迭代器

(正如其他人所说的) const _ iterator 不允许修改它所指向的元素,这在 const 类方法中很有用。它还允许你表达你的意图。

不幸的是,许多用于 STL 容器的方法使用 迭代器而不是 Const _ 迭代器作为参数。因此,如果有 Const _ iterator,就不能说“在迭代器指向的元素之前插入一个元素”(在我看来,这样说在概念上并不违反常量)。如果无论如何都要这样做,那么必须使用 预付款下一个()将其转换为非常数迭代器。艾格。Next (conter.start () ,std: : length (conter.start () ,the _ const _ iterator _ we _ want _ to _ unconst)).如果 集装箱列表,那么该呼叫的运行时间将是 O (n)

因此,在合乎逻辑的地方添加 const 的通用规则,对于 STL 容器来说就不那么通用了。

但是,升级容器使用 const _ iterators (例如,升级: : unorder _ map: : 擦除())。因此,当您使用升级容器时,可以使用“ const 咄咄逼人”。顺便问一下,有人知道 STL 容器是否或何时会被修复吗?

让我先用一个非常简单的例子来解释它,不用常量迭代器 考虑到我们有随机整数集合的集合

    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;

可以看到,在集合内写/编辑数据时使用了普通迭代器,但在读取时使用了常量迭代器。如果您尝试在 first for 循环中使用常量迭代器,您将得到错误。作为经验法则,使用常量迭代器读取集合中的数据。

最小可运行示例

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

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方法中使用 this:

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成为常数,这使 this->v成为常数。

对于 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 intint: 当您可以使用 const 迭代器时(当您不需要用它们修改容器时) ,更喜欢使用 const 迭代器,以便更好地记录您不需要修改就可以阅读的意图。