我正在编写(作为自学练习)一个简单的STL-Like范围。它是一个不可变随机访问“容器”。我的范围只保留其起始元素,元素数量和步长(两个连续元素之间的差异):
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
。现在,我可以假设const reference
和元素的副本在使用标准库中的非变异算法方面是相同的吗?
非常感谢有关该主题的任何建议。
@Steve Jessop:很好,你提到了迭代器。
实际上,我使用了sgi as my reference。在该页面的末尾,它说:
假设x和y是来自相同范围的迭代器:
不变量身份
x == y if and only if &*x == &*y
所以,它归结为我实际问过的同一个原始问题:)
答案 0 :(得分:1)
STL容器中的项目预计会一直被复制;例如,考虑何时必须重新分配向量。所以,你的例子很好,除了它只适用于随机迭代器。但我怀疑后者可能是设计上的。 :-P
答案 1 :(得分:1)
您希望您的范围可用于STL算法吗?使用第一个和最后一个元素会不会更好? (考虑到end()
是必需/使用的事实,你必须预先计算它的性能。)或者,你指望连续的元素(这是我的第二点)?
答案 2 :(得分:1)
标准算法并没有真正使用operator[]
,它们都是根据迭代器定义的,除非我忘记了重要的事情。是否计划在operator[]
之上为“范围”重新实现标准算法,而不是迭代器?
在非变异算法确实使用迭代器的情况下,它们都是根据*it
定义的,可以分配给它需要分配给它的任何东西,或者对某些指定的操作或函数调用有效。我认为所有或大多数此类操作都没有价值。
我能想到的一件事是,你不能传递一个预期非const引用的值。是否存在需要非const引用的非变异算法?可能不是,只要任何函子参数等都有足够的const
。
很抱歉,我不能肯定地说没有奇怪的角落出错,但听起来对我来说基本没问题。即使有任何问题,您也可以通过算法版本与标准版本之间的要求略有不同来修复它们。
编辑:可能出错的第二件事是使用指针/引用并保持它们太长。据我所知,标准算法不保留指向元素的指针或引用 - 原因是它的容器保证了指向元素的指针的有效性,迭代器类型只告诉你什么时候 iterator 保持有效(例如,当原始递增时,输入迭代器的副本不一定保持有效,而对于多遍算法,可以以这种方式复制转发迭代器)。由于算法没有看到容器,只看到迭代器,所以我没有理由认为这些元素是持久的。
答案 3 :(得分:1)
由于您将“容器”放在“引号”中,您可以随心所欲。
STL类型的东西(迭代器,容器上的各种成员函数..)返回引用,因为引用是左值,并且某些构造(即myvec [i] = otherthing)可以编译。想想std :: map上的operator []。对于const引用,我想这不是一个避免复制的值。
虽然方便,但这条规则一直受到侵犯。迭代器类将当前值存储在成员变量中也是很常见的,仅仅是为了返回引用或const引用(是的,如果迭代器是高级的,则此引用将无效)。
如果你对这类东西感兴趣,你应该查看boost迭代器库。