简体   繁体   English

C ++:使用const和STL迭代器

[英]C++: using const with STL iterators

From Effective C++ , Item 3 Effective C ++ ,第3项

/* case1 */ const std::vector<int>::iterator i  // i  acts like a T* const
/* case2 */ std::vector<int>::const_iterator ci // ci acts like a const T*

To remember how const applies, I used to remember the following from this article 为了记住const是如何应用的,我曾经记得本文中的以下内容

Basically 'const' applies to whatever is on its immediate left (other than if there is nothing there in which case it applies to whatever is its immediate right). 基本上'const'适用于其左边的任何东西(除非没有任何东西,在这种情况下它适用于它的直接权利)。

When I read the Item 3 in the book first, I expected it to be the other way round in case1 and case2. 当我首先阅读书中的第3项时,我预计它将在case1和case2中反过来。

Should I treat this case as an exception? 我应该把这个案子当作例外吗? Or is there some deeper level understanding that I am missing? 或者是否有一些我缺失的更深层次的理解?

The rule works as advertised. 该规则与宣传的一样有效。

const std::vector<int>::iterator i

The item on the immediate right is iterator : the iterator is immutable. 右边的项是iterator :迭代器是不可变的。 You cannot assign the iterator to point to different items in the vector, you cannot increment it, it always points to the item it is initialized to. 你不能指定迭代器指向向量中的不同项,你不能递增它,它总是指向它被初始化的项。 You can change the item being pointed to, though. 但是,您可以更改指向的项目。

This is rarely the desired behavior, which is why the const_iterator typedef exists. 这很少是期望的行为,这就是const_iterator typedef存在的原因。

std::vector<int>::const_iterator ci

The iterator can be moved around, but the item pointed to cannot be modified. 迭代器可以四处移动,但指向的项目无法修改。 This is pretty much always what you want--you want to iterate over a vector but not be able to modify its contents. 这几乎总是你想要的 - 你想迭代一个向量但不能修改它的内容。

There's no const keyword here so you can't use the rule to figure it out. 这里没有const关键字,因此您无法使用该规则来解决问题。 For this one you just have to understand what const_iterator is documented to do. 对于这个,您只需要了解const_iterator要记录的内容。

You can think of it being as if the iterators were typedef ed like so: 你可以认为这是因为,如果迭代器中的typedef编着,像这样:

typedef T* iterator;
typedef const T* const_iterator;

When you add const to either of these, it applies at the top level , that is, to the pointer itself, not to the object pointed to, so the following equivalencies hold: 当您将const添加到其中任何一个时,它将应用于顶层 ,即应用于指针本身,而不是指向的对象,因此以下等效项包含:

const iterator it; // is the same as:
T* const it;

const const_iterator it; // is the same as:
const T* const it;

They are not an exception; 它们也不例外; this is how all typedef s work. 这就是所有typedef的工作方式。

The rule quoted is absolutely true of the const keyword. 引用的规则绝对适用于const关键字。 However, when dealing with iterators, the const_iterator class is merely named so (it could equally be readonly_iterator ), so the rule about the const keyword does not apply. 但是,在处理迭代器时, const_iterator类仅被命名为(它同样可以是readonly_iterator ),因此关于const关键字的规则不适用。

You can however declare case 1 like this: 但是,您可以像这样声明案例1:

std::vector<int>::iterator const i

just like you can specify either const int x or int const x . 就像你可以指定const int xint const x

The type an iterator points to is also specified in the template parameter of its container, so the ordering is different to declaring ordinary variables. 迭代器指向的类型也在其容器的模板参数中指定,因此排序与声明普通变量不同。

I can't see that there's any particular rule of thumb to follow here - the comments in your post are the right idea, you just need to learn to treat const_iterator as const T* and so on. 我无法看到这里有任何特定的经验法则 - 你的帖子中的评论是正确的想法,你只需要学习将const_iterator视为const T*等等。

I think that the const_iterator is confusing you. 我认为const_iterator让你很困惑。 Here is an example with simpler typedefs. 这是一个更简单的typedef的例子。

typedef int* Type;
typedef const int* ConstType;

int main() {
  const Type a; // int * const
  ConstType b; // const int *
}

The const in case 1 applies to the iterator, so it makes the iterator itself const. 情况1中的const适用于迭代器,因此它使迭代器本身成为常量。 It doesn't have any effect on the item the iterator is "pointing to". 它对迭代器“指向”的项没有任何影响。 (This is like in T* const , where the pointer is const , not the pointed-to T ) (这就像在T* const ,其中指针是const ,而不是指向T

In case 2, the const is just part of the name const_iterator , so it can't really be deduced what is const there. 在第2种情况下, const只是名称const_iterator一部分,因此无法真正推断出const是什么。 The class could just have a bad name and there could be nothing const about it at all. 这个类可能只有一个坏名字,根本就没有关于它的const。 In this case however, the const_iterator doesn't allow modification of it's target element, because it is defined like that in the standard library. 但是在这种情况下, const_iterator不允许修改它的目标元素,因为它的定义与标准库中的类似。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM