代码之家  ›  专栏  ›  技术社区  ›  Khaled Alshaya

像STL的范围,如果我这样做会出什么问题?

  •  5
  • Khaled Alshaya  · 技术社区  · 15 年前

    我在写(作为一个自学练习)一个简单的stl-like范围。它是一个不可变的随机访问“容器”。我的范围,只保留ITS开始元素、元素数量和步骤大小(两个连续元素之间的差异):

    struct range
    {
    ...
    private:
      value_type m_first_element, m_element_count, m_step;
    };
    

    因为我的范围不包含元素,所以它使用以下方法计算所需的元素:

    // In the standards, the operator[]
    // should return a const reference.
    // Because Range doesn't store its elements
    // internally, we return a copy of the value.
    value_type operator[](size_type index)
    {
        return m_first_element + m_step*index;
    }
    

    如你所见,我不会退回 const reference 正如标准所说。现在, 我能假设 常量引用 在使用标准库中的非变异算法方面,元素的副本是相同的?

    关于这个问题的任何建议都非常感谢。


    @史蒂夫·杰索普:你提到迭代器的时候说得对。

    实际上,我用过 sgi as my reference . 在那一页的最后,它说:

    假设x和y是来自相同范围的迭代器:

    不变量恒等式
    x == y if and only if &*x == &*y

    所以,归根结底就是我问过的原来的问题:)

    4 回复  |  直到 15 年前
        1
  •  1
  •   Steve Jessop    15 年前

    标准算法并不真正使用 operator[] ,它们都是用迭代器定义的,除非我忘记了一些重要的东西。是否计划在 操作员[ ] 对于您的“范围”,而不是迭代器?

    在非变异算法确实使用迭代器的地方,它们都是根据 *it 可分配给需要分配给的任何对象,或对某些指定的操作或函数调用有效。我认为所有或大多数这样的操作都是有价值的。

    我能想到的一件事是,不能在需要非常量引用的地方传递值。有没有需要非常量引用的非变异算法?如果任何函数参数等都有足够的 const 在里面。

    所以,对不起,我不能肯定地说,没有奇怪的角落出错,但这听起来基本上是可以的。即使有任何麻烦,您也可以在您的算法版本和标准算法版本之间的需求上有非常小的差异来修复它们。

    编辑:第二件可能出错的事情是获取指针/引用并将它们保存得太长。据我所知,标准算法不保留对元素的指针或引用——原因是 容器 它保证指向元素的指针的有效性,迭代器类型只告诉您 迭代器 保持有效(例如,输入迭代器的副本在原始迭代器递增时不一定保持有效,而对于多通算法,可以用这种方式复制正向迭代器)。由于算法没有看到容器,只看到迭代器,所以我认为它们没有理由假定元素是持久的。

        2
  •  1
  •   C. K. Young    15 年前

    STL容器中的项目将一直被复制;例如,考虑何时必须重新分配向量。所以,您的示例很好,只是它只适用于随机迭代器。但我怀疑后者可能是故意的。:-p

        3
  •  1
  •   dirkgently    15 年前

    您希望您的范围在STL算法中可用吗?第一个元素和最后一个元素不是更好吗?(考虑到 end() 是否经常需要/使用,您将不得不预先计算它的性能。)或者,您是指望连续的元素(哪是我的第二点)?

        4
  •  1
  •   Terry Mahaffey    15 年前

    既然你把“容器”放在“引号”里,你就可以随心所欲了。

    stl-type-things(迭代器、容器上的各种成员函数..)返回引用,因为引用是lvalue,并且某些构造(即myvec[i]=otherthing)随后可以编译。想想std::map上的operator[]。对于常量引用,我想它不是一个值,只是为了避免复制。

    不过,在方便的时候,这条规则一直被违反。迭代器类将当前值存储在成员变量中也很常见,只是为了返回引用或常量引用(是的,如果迭代器是高级的,则此引用将无效)。

    如果您对这类东西感兴趣,您应该查看BoostIterator库。