C++ 类似STL的范围,如果我这样做会出什么问题?

C++ 类似STL的范围,如果我这样做会出什么问题?,c++,stl,standards,C++,Stl,Standards,我正在写(作为一个自学练习)一个简单的类似STL的范围。它是一个不可变的随机访问“容器”。“我的范围”仅保留其开始元素、元素数和步长(两个连续元素之间的差值): 由于“我的范围”不包含元素,因此它使用以下公式计算所需元素: // In the standards, the operator[] // should return a const reference. // Because Range doesn't store its elements // internally, we retu

我正在写(作为一个自学练习)一个简单的类似STL的范围。它是一个不可变的随机访问“容器”。“我的范围”仅保留其开始元素、元素数和步长(两个连续元素之间的差值):

由于“我的范围”不包含元素,因此它使用以下公式计算所需元素:

// 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;
}
正如您所看到的,我并没有像标准所说的那样返回
常量引用。现在,我可以假设
常量引用
和元素的副本在使用标准库中的非变异算法方面是相同的吗

任何关于这个问题的建议都将不胜感激


@史蒂夫·杰索普:你提到迭代器的观点很好

事实上,我用过。在那一页的末尾,它说:

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

不变量标识
x==y当且仅当&*x==&*y


因此,它可以归结为我实际上问过的同一个原始问题:)

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

您希望您的范围在STL算法中可用吗?有了第一个和最后一个元素不是更好吗?(考虑到经常需要/使用

end()
,您必须预先计算它的性能。)或者,您是否依赖于连续元素(这是我的第二点)?

标准算法实际上没有使用
运算符[]
,它们都是用迭代器定义的,除非我忘记了一些重要的东西。是否计划在
操作符[]
的基础上,为您的“范围”而不是迭代器重新实现标准算法

在非变异算法使用迭代器的情况下,它们都是根据
*it
定义的,可以分配给需要分配给的任何对象,或者对某些指定的操作或函数调用有效。我认为所有或大部分此类老年退休金都是有价值的

我能想到的一件事是,不能在需要非常量引用的地方传递值。是否存在需要非常量引用的非变异算法?如果任何函子参数等中有足够的
const
,则可能不会

很抱歉,我不能肯定地说,没有什么奇怪的角落会出错,但我觉得基本上没问题。即使有任何细微的差别,您也可以通过在您的算法版本和标准算法版本之间的要求上有细微的差异来解决这些问题

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

因为你把“容器”放在“引号”中,你可以做任何你想做的事

STL类型的东西(迭代器、容器上的各种成员函数..)返回引用,因为引用是左值,某些构造(即myvec[i]=otherthing)可以编译。想想std::map上的运算符[]。对于常量引用,我想它不是一个仅为了避免复制的值

但在方便的情况下,始终会违反此规则。同样常见的情况是,迭代器类将当前值存储在成员变量中纯粹是为了返回引用或常量引用(是的,如果迭代器处于高级状态,则此引用将无效)


如果您对这类内容感兴趣,您应该查看boost迭代器库。

如果您创建了一个元素以在运算符[]中返回然后返回了对它的引用,该引用是否总是一个错误的引用,因为实例会立即超出范围?
标准中谈到容器中的引用,那不是一个容器。@Chris我同意它不是一个真正的容器。这就是为什么我放“容器”在我上面第二句中的双引号之间。你可能想看看boost::iterator_range和boost::sub_range以获得灵感:你可以同时拥有“范围”对象和迭代器。我还认为您担心过度了:如果您的迭代器没有这个恒等式不变,那就这样吧。如果您按值返回,那么可能无法获取结果的地址。
end()
可以非常简单地计算:
m_first_element+m_step*m_element_count
,所以这真的不是一个问题。我写了使
range
成为一个不可变的随机访问容器所需的一切,除了我在问题中所说的:)这是我问题的第二部分:在容器的内存管理部分强加这个标准可以吗?对不起,我没有理解你的意思,你能详细说明一下吗:)
// 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;
}