Rust迭代器和C ++迭代器之间的主要区别是什么? [英] What are the main differences between a Rust Iterator and C++ Iterator?
问题描述
C ++迭代器的一个典型示例是指针,它可用于指向C数组中的元素,如下所示:
int array[] = {1, 2, 3, 4};
int* begin = std::begin(array); //Starting iterator
int* end = std::end(array) //Ending iterator
for(int* i = begin; i < end; i++)
{
std::cout << *i << ',';
}
//Prints 1, 2, 3, 4
这很简单.
中 cplusplus.com 的迭代器的定义是迭代器是指向一系列元素(例如数组或容器)中某个元素并能够使用一组运算符迭代该范围中的元素的任何对象... >
这很有道理;在上面的代码中,有两个迭代器(begin
和end
迭代器),并且使用了for
循环并递增.
在Rust中,像这样使用迭代器:
let vect = vec![1, 2, 3, 4];
let vect_iter = vect.iter();
什么?要对其进行迭代,请执行以下操作:
vect_iter.next();
vect_iter.next();
我在Rust文档中找不到指针的任何确切定义,而是在查看 Iterator
特征,似乎迭代器是容器的包装器,通过以某种方式标准化逻辑(如果完全有意义),可以简化处理./p>
我的主要问题是:
- 主要区别是什么?
- 为什么Rust会以这种方式使用迭代器,为什么它们表示的如此不同?
- C ++中有Rust类型的迭代器吗?
- Rust中有C ++类型的迭代器吗?
- 他们称呼某些特定内容吗? (内部/外部?)
迭代器是一种编程语言中的概念,用于指代允许对元素的集合或序列进行迭代的构造.这个概念故意是模糊的,这是一个概念!它没有规定任何具体的实现方式.
为了更轻松地将C ++与Rust区别开,我将使用不同的名称:
- C ++迭代器将被命名为光标,
- Rust迭代器将被命名为流.
是的,这些完全是任意的.请注意,如果您查看Java或C#之类的语言,则会发现它们也使用流.
C ++
首先,不要使用cplusplus.com. cppreference.com更好.
迭代器是指向一系列元素(例如数组或容器)中某个元素并能够使用一组运算符迭代该范围中的元素的任何对象... >
简单,错误.
光标可能是:
- 指向元素
- 或单数,并且完全不指向任何元素.
通常,奇异值用于表示:
- 要迭代的序列结尾:
vec.end()
, - 缺少元素:
std::find(...)
.
您可以增加,有时也可以减少光标.如果这样做,通常需要一个对游标才能知道何时停止.
为什么C ++使用这种表示形式?因为这就是C的工作方式,而且效果很好……尽管它很容易出错.
铁锈
尽一切努力确保安全,并青睐易于使用的API.这排除了一对游标:
- 一对游标并不安全:您可以轻松地进行边界迭代,并且可以获得别名引用,
- 一对游标容易出错:很容易意外地将两个不同序列中的游标配对.
为了控制边界,混淆并避免对不匹配,您必须使用单个对象;因此是类似流的API.
Rust中的Iterator
API让人想起Java和C#,尽管Rust通过使用Option<T>
对其进行了改进,所以它提供了一个单一的方法,而不是笨拙的hasNext()
/next()
调用对. next()
既可以使流前进,也可以用信号通知其结束.
结论
Rust和C ++都具有一种迭代元素集合的方式:
- C ++提供了一种类似于C的方式,灵活但容易出错,
- 铁锈提供了一种安全,但灵活性较差的现代方式.
两种语言还提供外部和内部迭代:
- 外部:用户控制迭代(调用
++
或next()
), - 内部:迭代器控制用户代码(请参见
std::foreach
和Iterator::foreach
).
A typical example of a C++ iterator is a pointer, and can be used to point at an element in a C array like so:
int array[] = {1, 2, 3, 4};
int* begin = std::begin(array); //Starting iterator
int* end = std::end(array) //Ending iterator
for(int* i = begin; i < end; i++)
{
std::cout << *i << ',';
}
//Prints 1, 2, 3, 4
This is simple enough. The definition of an iterator from cplusplus.com is
An iterator is any object that, pointing to some element in a range of elements (such as an array or a container), has the ability to iterate through the elements of that range using a set of operators...
This makes sense; in the above code there were two iterators (the begin
and the end
iterators), and it used a for
loop and incremented.
In Rust, an iterator is used like this:
let vect = vec![1, 2, 3, 4];
let vect_iter = vect.iter();
What? To iterate it you do:
vect_iter.next();
vect_iter.next();
I couldn't find any exact definition of a pointer in the Rust docs, but looking at the Iterator
trait, it is seems that an iterator is a wrapper for a container that enables for easier processing, by standardizing the logic in a way (if that makes sense at all).
The main questions I have are:
- What are the main differences?
- Why does Rust have iterators in this fashion and why are they expressed so differently?
- Are there Rust-type iterators in C++?
- Are there C++-type iterators in Rust?
- Are they called something specific? (Internal/External?)
An iterator is a concept found in programming languages to refer to a construct which allows iterating over collections or sequences of elements. The concept is purposely vague, it's a concept! It does not prescribe any specific implementation.
To more easily distinguish C++ from Rust, I am going to use different names:
- C++ iterators will be named cursors,
- Rust iterators will be named streams.
Yes, those are completely arbitrary. Note that if you look at languages like Java or C#, you will find that they also use streams.
C++
First of all, don't use cplusplus.com. cppreference.com is much better.
An iterator is any object that, pointing to some element in a range of elements (such as an array or a container), has the ability to iterate through the elements of that range using a set of operators...
Simple, and wrong.
A cursor may either:
- point to an element,
- or be singular and point to no element at all.
In general, the singular value is used to represent:
- the end of the sequence to iterate over:
vec.end()
, - the absence of an element:
std::find(...)
.
You can increment, and sometimes decrement, a cursor. If you do so, you however generally need a pair of cursors to know when to stop.
Why did C++ use such a representation? Because that's how C did it, and it works pretty well... although it's error prone.
Rust
Rust endeavors to be safe and favors APIs which are easy to use. This rules out a pair of cursors:
- a pair of cursors is not safe: you can easily iterate out of bounds, and you can obtain aliasing references,
- a pair of cursors is error-prone: it's easy to accidentally pair off cursors from two different sequences.
In order to control bounds, aliasing and avoid pair mismatch, you have to use a single object; thus the stream-like API.
The Iterator
API in Rust is reminiscent of that of Java and C#, although Rust improves upon it by using Option<T>
so that instead of the clumsy hasNext()
/next()
call pair, it offers a single method next()
which both advances the stream and may signal its end.
Conclusion
Both Rust and C++ features a way to iterate over a collection of elements:
- C++ offers a C-like way, flexible but error-prone,
- Rust offers a modern way, safe but less flexible.
Both languages also offer external and internal iteration:
- External: the user controls the iteration (calls
++
ornext()
), - Internal: the iterator controls the user code (see
std::foreach
andIterator::foreach
).
这篇关于Rust迭代器和C ++迭代器之间的主要区别是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!