【问题标题】:Why do I need to dereference iterators?为什么我需要取消引用迭代器?
【发布时间】:2013-06-22 03:43:00
【问题描述】:

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

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

【问题讨论】:

  • 请注意,您引用的代码没有意义,因为您将布尔值分配给循环内的字符。您可能想改用toupper()
  • 是的。发布问题几秒钟后,我意识到这一点。哈哈!
  • 你指的是dereferencing,而不是引用。
  • 什么是大写迭代器?
  • @user2474562:解决问题而不是回复,因为这样可以避免一些可怜的混蛋浪费时间(你永远不知道复制粘贴了什么)。

标签: c++ c++11 iterator


【解决方案1】:

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

例如:

int* x = ...;

x++;

你的意思是你想增加指针,让它指向内存中的下一个 int 吗?还是要增加 x 指向的 int?

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

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

与参考文献对比:

int& x = ...;

x++;

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

【讨论】:

    【解决方案2】:

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

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

    必须有 some 操作来表明你想引用它所引用的东西而不是迭代器本身,否则如果你测试 if (it == another_it) 编译器如何知道你是否试图比较迭代器或它们指向的东西? ++it 操作也是如此,它想要修改迭代器,而不是它指向的东西。

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

    【讨论】:

      【解决方案3】:

      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);
      

      【讨论】:

      • 嘿,谢谢。我目前正在阅读 C++ 入门第 5 版。一切都会好起来的。有什么更好的可以推荐吗?我看过你发的帖子,但我经验不足,无法挑出好的帖子。
      • @Armen toupper 是一个重载函数,您的 transform 示例不能保证工作。见gcc.gnu.org/onlinedocs/libstdc++/manual/…
      • @JonathanWakely 有人告诉我,将可能的负值传递给 &lt;cctype&gt; 是形式上未定义的行为,应该始终将参数转换为 unsigned char
      • @user2474562:C++Primer 是要走的路,IMO
      • @jrok,它必须 representableunsigned char(或等于EOF),因此如果它们适合unsigned char,则负值是可以的
      猜你喜欢
      • 2018-03-19
      • 2016-08-01
      • 2016-12-08
      • 2010-11-16
      • 1970-01-01
      • 2018-01-20
      • 2016-10-31
      • 2017-02-19
      • 2011-10-10
      相关资源
      最近更新 更多