【问题标题】:Returning Iterators instead of underlying Container itself when access to the Container needed当需要访问容器时返回迭代器而不是底层容器本身
【发布时间】:2012-01-26 01:15:54
【问题描述】:

在我的程序中有很多地方我需要访问和修改 std::map 数据结构。现在我有一个名为 getMap() 的方法,它本质上返回对 std::map 的引用。我正在考虑将迭代器返回到 std::map 而不是映射本身,以获得更好的封装和性能。就封装和性能而言,做这样的事情还是返回地图与返回迭代器一样好是个好主意吗?

【问题讨论】:

  • 我会从面向对象的角度说这是糟糕的设计。最好是保存地图的类具有可以执行您需要的操作的方法。
  • 这样返回迭代器对你没有任何好处。提前考虑如何接收迭代器: std::map::iterator it = getMapIterator();请注意,您已经重新声明了映射(语法方面)。如果您想节省一些打字时间 - 这不是解决问题的方法。当然,您可以 typedef 声明,但这只会增加更多的混乱。应用程序的不同部分持有不同的迭代器 - 事情会变得非常混乱。考虑做出坚定的决定,坚持使用对地图的引用,而不是返回迭代器

标签: c++ stl map iterator


【解决方案1】:

如果您真的只需要引用 map 那么为什么要返回迭代器?

如果您需要指向地图的特定部分,迭代器并不总是能很好地封装(它们是 const 吗?反向?随机访问......?您的调用例程可能希望免受此类细节的影响,并且裸迭代器不提供这种保护)。 boost::range 可能会提供更好的解决方案。

对于其他一些容器(例如vector),如果另一个例程在使用之前修改了容器,则迭代器将失效。根据程序的语义,您可能会认为这会破坏封装。

【讨论】:

  • Map 有一个重要的属性,即在 map 中插入一个新元素不会使指向现有元素的迭代器失效。从映射中擦除元素也不会使任何迭代器无效,当然,实际上指向被擦除元素的迭代器除外。
【解决方案2】:

我过去也做过同样的事情,但现在更喜欢返回对整个集合的引用。我担心迭代器保持有效。例如,如果我使用迭代器删除一个条目,它们是否仍然有效,还是我需要再次获取它们?归还藏品感觉像暴露更多,但我觉得这样更安全。

【讨论】:

    【解决方案3】:

    我认为当您返回整个地图的迭代器时,您会降低函数的实用性。该函数的使用者可以简单地编写 getMap().begin() 来获取迭代器。另一方面,他们可能对元素根本不感兴趣,他们可能想clear()it 或swap()it。

    但是,当输出集合的某些 子集 时,例如通过谓词选择的范围或某些元素,通过输出迭代器返回数据比返回 reduced 集合要好得多。

    标准库一直这样做,例如copy()算法:

    template<class InputIterator, class OutputIterator>
        OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result )
    {
        while (first!=last) *result++ = *first++;
        return result;
    }
    

    这里result 可以将元素附加到另一个集合类(使用back_inserter),输出到屏幕,甚至处理元素而不将它们存储在任何地方,例如计算集合中项目的统计信息。

    【讨论】:

    • 我并没有真正遵循这里的答案。你是说返回迭代器是个坏主意吗?但是接受 OutputIterator 的函数是可以的。可能是我错过了一些东西。另外,您提到了 generate() 算法,但在示例中它是 copy()。
    • @PavanTotala "generate" 是一个错字,我会修正它。我的观点是将迭代器返回到整个地图是没有用的,用户可以使用 myMap().begin() 来做到这一点。在第二段中,我打算指出返回集合的某些子集,例如过滤的子集或范围,返回迭代器是一种非常灵活的方式。我会编辑。
    • @PavanTotala:我写的时候一定是睡着了。我已经对它进行了大量编辑,如果更清楚请告诉我。
    猜你喜欢
    • 2012-04-26
    • 1970-01-01
    • 2011-06-21
    • 2012-06-16
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2014-02-02
    相关资源
    最近更新 更多