0

为什么我需要取消引用迭代器?例如在以下程序中

#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;
}

为什么需要 useisupper(*it);而不是 just isupper(it);

4

3 回答 3

11

迭代器是一个通用指针。它指向某事。如果您有一个需要某些东西的函数(在这种情况下是 char 或 int),而不是“指针”本身,则需要取消引用迭代器。

例如,标准advance函数将迭代器作为其参数。因此,您传递迭代器而不取消引用它,如

std::advance(it, n);

但是如果你有一个指向 int 的迭代器并且你想将该整数增加 4,你需要

(*it) += 4;

我建议你应该阅读一本关于 C++ 的好书

顺便说一句,你的整个循环可以被一个调用 transform 替换

 std::transform(s.begin(), s.end(), s.begin(), toupper);
于 2013-06-25T11:10:32.820 回答
4

您需要能够对迭代器本身执行操作,例如您的代码执行it != s.end()++it

有时您需要能够对迭代器指向的对象执行操作,例如isupper(*it)

必须有一些操作来表明您要引用它所引用的东西而不是迭代器本身,否则如果您测试 if (it == another_it)编译器如何知道您是在尝试比较迭代器还是它们指向的东西?这同样适用于++it想要修改迭代器的操作,而不是它指向的东西。

迭代器可以有一个get()成员来返回它们所引用的东西,所以你会这样做,isupper(it.get())但它们支持解引用运算符,它的类型更少并且与指针一致,并允许在任何需要迭代器的代码中使用指针。

于 2013-06-25T11:33:15.480 回答
2

为了区分指针 T 上的操作和主题 T 上的操作,有必要有一个解引用运算符。

例如:

int* x = ...;

x++;

你的意思是你想增加指针,使它指向内存中的下一个 int 吗?或者你想增加 x 指向的 int 吗?

如果没有引用运算符,这将是模棱两可的。

迭代器只是指针接口的泛化。

对比参考:

int& x = ...;

x++;

引用具有替代语义,并且不需要取消引用。对 T 的引用的操作适用于主题 T。缺点是您不能修改引用本身。

于 2013-06-25T12:14:33.230 回答