C++ 中的 const_iterator 和非常量迭代器有什么区别? 标准格式?

发布于 2024-07-09 17:32:04 字数 79 浏览 6 评论 0原文

const_iteratoriterator 之间有什么区别?您会在哪里使用其中一个?

What is the difference between a const_iterator and an iterator and where would you use one over the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

乖乖兔^ω^ 2024-07-16 17:32:04

const_iterator 不允许您更改它们指向的值,而常规迭代器则可以。

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

const_iterators don't allow you to change the values that they point to, regular iterators do.

As with all things in C++, always prefer const, unless there's a good reason to use regular iterators (i.e. you want to use the fact that they're not const to change the pointed-to value).

鸠魁 2024-07-16 17:32:04

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

They should pretty much be self-explanatory. If iterator points to an element of type T, then const_iterator points to an element of type 'const T'.

It's basically equivalent to the pointer types:

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

A const iterator always points to the same element, so the iterator itself is const. But the element it points to does not have to be const, so the element it points to can be changed.
A const_iterator is an iterator that points to a const element, so while the iterator itself can be updated (incremented or decremented, for example), the element it points to can not be changed.

奈何桥上唱咆哮 2024-07-16 17:32:04

最小可运行示例

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

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 性返回 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 和非常量非常相似,您可以轻松地从非常量转换为 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 迭代器(当您不需要用它们修改容器时),就更喜欢使用它们,以更好地记录您无需修改​​的阅读意图。

Minimal runnable examples

Non-const iterators allow you to modify what they point to:

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

Const iterators don't:

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;

As shown above, v.begin() is const overloaded, and returns either iterator or const_iterator depending on the const-ness of the container variable:

A common case where const_iterator pops up is when this is used inside a const method:

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 makes this const, which makes this->v const.

You can usually forget about it with auto, but if you starting passing those iterators around, you will need to think about them for the method signatures.

Much like const and non-const, you can convert easily from non-const to const, but not the other way around:

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;

Which one to use: analogous to const int vs int: prefer const iterators whenever you can use them (when you don't need to modify the container with them), to better document your intention of reading without modifying.

睫毛溺水了 2024-07-16 17:32:04

不幸的是,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)

因此,当涉及到 STL 容器时,在任何“合乎逻辑”的地方添加 const 的通用规则就不那么通用了。

然而,boost 容器采用 const_iterators(例如 boost::unordered_map::erase())。 因此,当您使用 boost 容器时,您可以变得“非常激进”。 顺便问一下,有谁知道 STL 容器是否或何时会被修复?

Unfortunaty, a lot of the methods for the STL containers takes iterators instead of const_iterators as parameters. So if you have a const_iterator, you can't say "insert an element before the element that this iterator points to" (saying such a thing is not conceptually a const violation, in my opinion). If you want do that anyway, you have to convert it to a non-const iterator using std::advance() or boost::next(). Eg. boost::next(container.begin(), std::distance(container.begin(), the_const_iterator_we_want_to_unconst)). If container is a std::list, then the running time for that call will be O(n).

So the universal rule to add const wherever it is "logical" to do so, is less universal when it comes to STL containers.

However, boost containers take const_iterators (eg. boost::unordered_map::erase()). So when you use boost containers you can be "const agressive". By the way, do anyone know if or when the STL containers will be fixed?

我们只是彼此的过ke 2024-07-16 17:32:04

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

Use const_iterator whenever you can, use iterator when you have no other choice.

迷途知返 2024-07-16 17:32:04

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

(as others have said) const_iterator doesn't allow you modify the elements to which it points, this is useful inside of const class methods. It also allows you to express your intent.

酷到爆炸 2024-07-16 17:32:04

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

ok Let me explain it with very simple example first without using constant iterator
consider we have collection of random integers collection "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;

As can be seen for writing/editing data inside collection normal iterator is used but for reading purpose constant iterator has been used . If you try using constant iterator in first for loop you will get error . As a thumb rule use constant iterator to read data inside collection .

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文