const_iterator
a和 an有什么区别,iterator
你会在哪里使用一个而不是另一个?
7 回答
const_iterator
s 不允许您更改它们指向的值,常规iterator
s 可以。
与 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 元素的迭代器,因此虽然迭代器本身可以更新(例如,递增或递减),但它指向的元素不能更改。
不幸的是,许多 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 容器是否或何时会修复?
尽可能使用const_iterator ,别无选择时使用iterator 。
最小的可运行示例
非常量迭代器允许您修改它们指向的内容:
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
使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 迭代器(当您不需要用它们修改容器时),就更喜欢它们,以便更好地记录您在不修改的情况下阅读的意图。
(正如其他人所说) 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 循环中使用常量迭代器,您将得到错误。作为一个经验法则,使用常量迭代器来读取集合内的数据。