165

const_iteratora和 an有什么区别,iterator你会在哪里使用一个而不是另一个?

4

7 回答 7

149

const_iterators 不允许您更改它们指向的值,常规iterators 可以。

与 C++ 中的所有内容一样,始终喜欢const,除非有充分的理由使用常规迭代器(即,您想使用它们不会const更改指向值的事实)。

于 2008-11-21T17:39:25.253 回答
47

它们几乎应该是不言自明的。如果 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 元素的迭代器,因此虽然迭代器本身可以更新(例如,递增或递减),但它指向的元素不能更改。

于 2008-11-21T17:51:09.473 回答
8

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

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

但是,boost 容器采用 const_iterators(例如 boost::unordered_map::erase())。因此,当您使用 boost 容器时,您可以“积极进取”。顺便说一句,有人知道 STL 容器是否或何时会修复?

于 2010-09-02T16:18:15.773 回答
7

尽可能使用const_iterator ,别无选择时使用iterator 。

于 2008-11-21T17:51:33.607 回答
7

最小的可运行示例

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

std::vector<int> v{0};
std::vector<int>::iterator it = v.begin();
*it = 1;
assert(v[0] == 1);

常量迭代器不会:

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重载,并根据容器变量的 const-ness返回iterator或返回:const_iterator

const_iterator弹出的常见情况是在方法this中使用when 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使thisconst,从而使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 迭代器(当您不需要用它们修改容器时),就更喜欢它们,以便更好地记录您在不修改的情况下阅读的意图。

于 2016-12-22T02:55:04.043 回答
0

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

于 2008-11-21T18:42:17.683 回答
0

好的,让我先用一个非常简单的例子来解释它,而不使用常量迭代器考虑我们有随机整数集合“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 循环中使用常量迭代器,您将得到错误。作为一个经验法则,使用常量迭代器来读取集合内的数据。

于 2011-01-17T06:32:18.577 回答