如何实现 STL 风格的迭代器并避免常见的陷阱?

2024-03-31

我创建了一个集合,我想为其提供一个 STL 风格的随机访问迭代器。我正在寻找迭代器的示例实现,但没有找到。我知道需要 const 重载[] and *运营商。迭代器“STL 风格”的要求是什么?还有哪些其他需要避免的陷阱(如果有)?

附加上下文:这是针对一个库的,除非我确实需要,否则我不想引入任何对它的依赖。我编写自己的集合,以便能够使用相同的编译器提供 C++03 和 C++11 之间的二进制兼容性(因此没有可能会破坏的 STL)。


https://cplusplus.com/reference/iterator/ https://cplusplus.com/reference/iterator/有一个方便的图表,详细介绍了 C++11 标准第 24.2.2 节的规范。基本上,迭代器具有描述有效操作的标签,并且标签具有层次结构。下面纯粹是象征性的,这些类实际上并不存在。

iterator {
    iterator(const iterator&);
    ~iterator();
    iterator& operator=(const iterator&);
    iterator& operator++(); //prefix increment
    reference operator*() const;
    friend void swap(iterator& lhs, iterator& rhs); //C++11 I think
};

input_iterator : public virtual iterator {
    iterator operator++(int); //postfix increment
    value_type operator*() const;
    pointer operator->() const;
    friend bool operator==(const iterator&, const iterator&);
    friend bool operator!=(const iterator&, const iterator&); 
};
//once an input iterator has been dereferenced, it is 
//undefined to dereference one before that.

output_iterator : public virtual iterator {
    reference operator*() const;
    iterator operator++(int); //postfix increment
};
//dereferences may only be on the left side of an assignment
//once an output iterator has been dereferenced, it is 
//undefined to dereference one before that.

forward_iterator : input_iterator, output_iterator {
    forward_iterator();
};
//multiple passes allowed

bidirectional_iterator : forward_iterator {
    iterator& operator--(); //prefix decrement
    iterator operator--(int); //postfix decrement
};

random_access_iterator : bidirectional_iterator {
    friend bool operator<(const iterator&, const iterator&);
    friend bool operator>(const iterator&, const iterator&);
    friend bool operator<=(const iterator&, const iterator&);
    friend bool operator>=(const iterator&, const iterator&);

    iterator& operator+=(size_type);
    friend iterator operator+(const iterator&, size_type);
    friend iterator operator+(size_type, const iterator&);
    iterator& operator-=(size_type);  
    friend iterator operator-(const iterator&, size_type);
    friend difference_type operator-(iterator, iterator);

    reference operator[](size_type) const;
};

contiguous_iterator : random_access_iterator { //C++17
}; //elements are stored contiguously in memory.

你可以专攻std::iterator_traits<youriterator>,或者将相同的 typedef 放入迭代器本身,或者继承自std::iterator(有这些类型定义)。我更喜欢第二种选择,以避免改变std命名空间,并且为了可读性,但大多数人继承自std::iterator.

struct std::iterator_traits<youriterator> {        
    typedef ???? difference_type; //almost always ptrdiff_t
    typedef ???? value_type; //almost always T
    typedef ???? reference; //almost always T& or const T&
    typedef ???? pointer; //almost always T* or const T*
    typedef ???? iterator_category;  //usually std::forward_iterator_tag or similar
};

请注意 iterator_category 应该是以下之一std::input_iterator_tag, std::output_iterator_tag, std::forward_iterator_tag, std::bidirectional_iterator_tag, or std::random_access_iterator_tag,取决于您的迭代器满足哪些要求。根据您的迭代器,您可以选择专门化std::next, std::prev, std::advance, and std::distance也是如此,但这很少需要。在极其罕见您可能希望专门研究的案例std::begin and std::end.

你的容器可能还应该有一个const_iterator,这是一个(可能可变的)常量数据迭代器,类似于您的iterator除非它应该可以从 a 隐式构造iterator并且用户应该无法修改数据。其内部指针通常是指向非常量数据的指针,并且具有iterator继承自const_iterator从而尽量减少代码重复。

我的帖子在编写您自己的 STL 容器 https://stackoverflow.com/questions/7758580/writing-your-own-stl-container/7759622#7759622有更完整的容器/迭代器原型。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何实现 STL 风格的迭代器并避免常见的陷阱? 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • BASIC 中的 C 语言中的 PeekInt、PokeInt、Peek、Poke 等效项

    我想知道该命令的等效项是什么Peek and Poke 基本和其他变体 用 C 语言 类似PeekInt PokeInt 整数 涉及内存条的东西 我知道在 C 语言中有很多方法可以做到这一点 我正在尝试将基本程序移植到 C 语言 这只是使用
  • 在模板类中声明模板友元类时出现编译器错误

    我一直在尝试实现我自己的链表类以用于教学目的 我在迭代器声明中指定了 List 类作为友元 但它似乎无法编译 这些是我使用过的 3 个类的接口 Node h define null Node
  • 没有特殊字符的密码验证器

    我是 RegEx 的新手 已经进行了大量搜索 但没有找到任何具体内容 我正在编写一个验证密码字符串的正则表达式 可接受的字符串必须至少具有 4 种字符类型中的 3 种 数字 小写字母 大写字母 特殊字符 我对包含有一个想法 也就是说 如果这
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • C# - 当代表执行异步任务时,我仍然需要 System.Threading 吗?

    由于我可以使用委托执行异步操作 我怀疑在我的应用程序中使用 System Threading 的机会很小 是否存在我无法避免 System Threading 的基本情况 只是我正处于学习阶段 例子 class Program public
  • 如何定义一个可结构化绑定的对象的概念?

    我想定义一个concept可以检测类型是否T can be 结构化绑定 or not template
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • 为什么 isnormal() 说一个值是正常的,而实际上不是?

    include
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern

随机推荐

  • R:加速“group by”操作

    我有一个模拟 中间有一个巨大的聚合和组合步骤 我使用 plyr 的 ddply 函数对这个过程进行了原型设计 它可以很好地满足我的大部分需求 但我需要更快的聚合步骤 因为我必须运行 10K 次模拟 我已经在并行扩展模拟 但如果这一步骤更快
  • 设计:新错误(可加密)

    我已经一周没有碰过我的代码了 但是当我捆绑并尝试运行我的网络服务器时 我现在收到以下错误 这让我死在了水里 按照错误输出中的建议包含可设计加密的 gem 并不能解决问题 并且仍然会导致相同的错误 任何帮助是极大的赞赏 DEVISE Devi
  • Reactjs:使用 shouldComponentUpdate() 停止在特定状态更改时重新渲染

    我的组件 onload 中有多个 setState 我的页面在单击下拉值时重新呈现 因为单击时我通过以下方式存储这些值setState 为了停止点击时重新渲染 我使用下面的代码 shouldComponentUpdate return fa
  • Nginx 反向代理配置

    我在使用 nginx 进行简单配置时遇到问题 我有一台托管 docker 容器的服务器 因此 nginx 位于容器中 所以我们调用 urlfoo com 我想要网址foo com service1实际上只是去另一个端口上的 foo com
  • CSS 中如何使用“大于”或“>”字符?

    我在 CSS 文件中多次看到这个字符 但我不知道它是如何使用的 谁能向我解释一下并展示它们如何使页面样式变得更容易 这是一个 CSS 子选择器 P gt SPAN表示将以下样式应用于作为子级的所有 SPAN 标记P tag 请注意 孩子 的
  • Visual Studio Code 中是否有像 DocBlockr 这样的代码注释功能?

    我使用 Sublime Text 3 Atom io 和 Bracket io 作为以前的编辑器 我也非常喜欢新的 Mac 版 Visual Studio 代码编辑器 Sublime 有类似 DocBlockr 的代码注释功能吗 这对我来说
  • Android Studio 0.5.9错误代码42

    每次我尝试从 eclipse 导入项目时 我都会收到这样的错误 Error Execution failed for task app mergeDebugResources 错误 无法运行命令 D Android sdk build to
  • 如何优化间接基数排序? (又名如何优化不可预测的内存访问模式)

    我用 C 编写了一个间接基数排序算法 间接 我的意思是它返回项目的索引 include
  • Kubernetes TLS 秘密证书过期

    我使用 openssl 创建通配符自签名证书 我将证书有效期设置为 到十年 我通过使用 openssl 检查证书来仔细检查有效期 我使用步骤 1 中准备的私钥和证书创建一个 Kubernetes 密钥 如下所示kubectl命令 kubec
  • 如何从ocaml列表中获取子列表

    我正在查看列表文档 图书馆好像没有提供sublist功能 我正在尝试从中获取元素列表i to j 现在我必须把它写成 let rec sublist list i j if i gt j then else List nth list i
  • 如何解析会导致非法 C# 标识符的 JSON 字符串?

    我一直在使用NewtonSoft JSON 转换 http james newtonking com json用于解析 JSON 字符串并将其转换为 C 对象的库 但现在我遇到了一个非常尴尬的 JSON 字符串 我无法将其转换为 C 对象
  • JavaMail 与 Oauth 和 Office365

    我正在用 Java 构建一个简单的命令行应用程序 它可以登录我的电子邮件箱 IMAP 并下载所有附件 我使用了基本身份验证 但 Microsoft 正在禁用它 因此我尝试将我的应用程序转换为使用 OAuth 在阅读了不同的 OAuth 流程
  • 部署时出现 aws beanstalk 403 错误

    您好 我正在使用亚马逊网络服务弹性豆茎 每次我使用 git aws push 时 我的 php 应用程序都会成功上传但是 当我单击 url 时 它会显示 Forbidden You don t have permission to acce
  • 自旋锁与忙等待[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 请解释原因忙碌等待通常不受欢迎 而Spinning通常被认为还可以 据我所知 它们都会无限循环 直到满足某些条件 A 自旋锁通常在资源争用较少时
  • 使用Mysql lower_case_table_names为1

    我已经使用 yum 在 linux 中安装了 mysql v5 5 17 现在我想要默认的小写表名 所以我添加了 set variable lower case table names 1 in etc my cnf 但如果我这样做 我就无
  • 获取安装目录安装盾

    我想通过安装盾来创建我的设置 我使用命令参数Setup exe path SETUPEXEDIR log txt我的设置位置是Desktop myapp Setup exe使用 SETUPEXEDIR 时返回临时文件夹 我希望在使用 SET
  • 为什么我不能让单个 Redis 客户端在同一连接中充当 PUB 和 Sub ?

    我的思维模型是 聊天 我订阅了某个频道 并且可以向该频道发布消息 由于 pub sub 是异步的 因此发布的消息可能随时出现 包括当您期望命令响应时 尽管 Redis 是单线程的 通常会阻止此类事情 但网络延迟可能会导致一些有趣的影响 根据
  • 如何修复“属性没有初始值设定项并且未在构造函数中明确分配”错误?

    我对这些课程有疑问 我想使用该方法doSomething 班级独有B无需每次都进行类型转换 但是当我指定属性时a属于类型B 它告诉我它没有在构造函数中分配 这有点错误 因为父构造函数进行了分配 class A class B extends
  • 在 Android 模拟器上安装 Flash Player

    我想知道在android模拟器上安装flash播放器的过程 请详细 我需要执行此操作来测试应用程序 但目前我没有任何物理设备 我已经尝试过的事情 1 我已经检查了有关此主题的所有堆栈溢出链接 2 我已经知道adobe已经停止了android
  • 如何实现 STL 风格的迭代器并避免常见的陷阱?

    我创建了一个集合 我想为其提供一个 STL 风格的随机访问迭代器 我正在寻找迭代器的示例实现 但没有找到 我知道需要 const 重载 and 运营商 迭代器 STL 风格 的要求是什么 还有哪些其他需要避免的陷阱 如果有 附加上下文 这是