为什么我需要取消引用迭代器?例如,在以下程序中
#include <iostream>
#include <string>
#include <vector>
int main()
{
using namespace std;
string s("some string");
for(auto it = s.begin(); it != s.end(); && !isspace(*it); ++it)
*it = isupper(*it);
cout<<s;
}
为什么有必要使用isupper(*it);
而不只是isupper(it);
?
答案 0 :(得分:10)
Iterator是一个通用指针。它指向。如果你有一个需要某些东西的函数(在这种情况下是char或int),而不是“指针”本身,你需要取消引用迭代器。
例如,标准advance
函数将迭代器作为参数。因此,您无需解除引用即可传递迭代器,如
std::advance(it, n);
但是如果你有一个指向int的迭代器而你想要将该整数增加4,那么你需要
(*it) += 4;
我建议您阅读a good book on C++。
顺便说一下,整个循环可以被一次调用替换
std::transform(s.begin(), s.end(), s.begin(), toupper);
答案 1 :(得分:4)
您需要能够对迭代器本身执行操作,例如您的代码it != s.end()
和++it
有时您需要能够对迭代器指向的对象执行操作,例如isupper(*it)
必须有一些操作来表示你想引用它引用的东西而不是迭代器本身,否则如果你测试if (it == another_it)
编译器怎么知道你是不是试图比较迭代器或它们指向的东西?这同样适用于++it
操作,它想要修改迭代器,而不是它指向的东西。
迭代器可以有一个get()
成员来返回他们引用的东西,所以你要做isupper(it.get())
但是他们支持解除引用操作符,这样可以减少输入并且与指针一致并允许指向要在任何期望迭代器的代码中使用的指针。
答案 2 :(得分:1)
为了区分指针到T的操作和对主题T的操作,必须有一个解除引用操作符。
例如:
int* x = ...;
x++;
你的意思是你想增加指针,使其指向内存中的下一个int?或者你想增加x指向的int?
如果没有差别算子,这将是不明确的。
迭代器只是指针接口的泛化。
与参考文献对比:
int& x = ...;
x++;
引用具有替代语义,不需要解除引用。对引用T的操作适用于主题T.缺点是您无法修改引用本身。