数组可以在 c++ 中用作迭代器吗?
我只是浏览 std::vector 构造函数,看到有些人使用带有 2 个迭代器的构造函数,并将其与数组一起使用,例如:
int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])
为什么这有效?那么数组也只是一个迭代器吗? 这里还有一个问题:
int a[5] = {0, 1, 2, 3, 4};
vector<int> v4(a, *(&a + 1));
这到底是做什么的以及为什么它与上面的另一件事不同?
I'm just looking through std::vector constructors and seeing some people use the constructor that takes 2 iterators and just use it with arrays like:
int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])
Why does this work? So is an array just an iterator as well?
Also one more question here:
int a[5] = {0, 1, 2, 3, 4};
vector<int> v4(a, *(&a + 1));
What exactly is this doing and why is it different from the other thing above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是行不通的。
数组不是迭代器。但是数组可以隐式转换为指向第一个元素的指针,该元素是数组的迭代器。
是一种不必要的复杂书写方式:
This doesn't work.
An array is not an iterator. But an array can implicitly convert to a pointer to first element which is an iterator for the array.
This is an unnecessarily complex way of writing:
这里的arr(如begin=arr)是一个“指针”,可以像迭代器一样使用。所以
begin=arr
是一个指向数组开头的“迭代器”,而end
是一个指向“beginning + 5”的“迭代器”。更精确一点:这里数组的名称“衰减”为指针。在许多情况下,名称可以用作指针,类似于
&arr[0]
,即指向第一个元素的指针。构造
sizeof(array )/sizeof(*array)
回到旧的 C 时代,返回数组中的元素数量。sizeof
本身仅返回以字节为单位的大小,但如果将其除以单个元素的大小,则可以获得元素的数量。现在您有了正确的“开始”和“结束”迭代器,您可以从中构造一个
std::vector
。它只是向量的构造函数之一,它需要两个迭代器。你的其他问题与第一个问题完全不同。
向量v4(a, *(&a + 1));
现在我不确定这是否完全有意义。也许你这里有错字。这将尝试调用一个向量构造函数,将
int[]
或int*
作为第一个参数,将 int 作为第二个参数。签名将是
std::vector::vector(int*, int)
,但我在 cppreference。Here
arr
(as in begin=arr) is a "pointer", which can be used like an iterator. Sobegin=arr
is an "iterator" to the beginning of the array andend
is an "iterator" to the "beginning + 5".To be a little more precise: Here the name of the array "decays" into a pointer. In many circumstances the name can be used as a pointer and would be similar to
&arr[0]
, i.e. a pointer to the first element.The construction
sizeof(array)/sizeof(*array)
goes back to the old C days and returns the number of elements in an array.sizeof
by itself only returns the size in bytes, but if you divide that by the size of a single element, you get the number of elements.So now that you have a correct "begin" and "end" iterator, you can construct a
std::vector<int>
from it. It's just one of the constructors of vector, which takes two iterators.Your other questions is completely different from the first one.
vector<int> v4(a, *(&a + 1));
Now I am not sure this makes entirely sense. Perhaps you have typo here. This would try to call a vector constructor taking an
int[]
orint*
as the first parameter and an int as the second parameter.The signature would be
std::vector<int>::vector(int*, int)
, but I do not see such a constructor in the cppreference.对于初学者来说,有一个拼写错误,
您的意思似乎是
虽然如果您的编译器支持 C++ 17,您可以编写
在具有罕见异常的表达式中使用的数组将转换为指向其第一个元素的指针。
来自 C++ 17 标准(7.2 数组到指针的转换)
考虑以下演示程序。
循环
它的输出可能会像从输出中看到的那样
,数组指示符
arr
被转换为表达式arr + 0
中的指针。如果将数组用作参数表达式,并且当数组转换为指向其第一个元素的指针时,相应的参数类型不是引用类型,则同样的方式。类模板
std::vector
中没有第一个参数具有数组引用类型的构造函数。但是有一个模板构造函数接受相同类型的两个第一个参数,
因此在此声明中
使用了两个上述构造函数,其中两个第一个参数转换为
int *
类型的指针。指针与随机访问迭代器具有相同的操作。因此,向量是使用整数值范围
[arr, arr + sizeof( arr ) / sizeof( arr[0] )
创建的对于此表达式
,则表达式 &a 的类型为
int ( * )[5]
指向数组 a.. 表达式&a + 1
指向数组最后一个元素的地址。解除引用的表达式 *(&a + 1) 的类型为 int[5],表示再次用作表达式的数组,该数组将转换为int *
类型的指针。因此,实际上在此声明中有两个
int *
类型的表达式。但是,这种方法并不正确,因为您可能无法取消引用指向有效对象的指针。
For starters there is a typo
It seems you mean
Though if your compiler supports the C++ 17 you could write
Arrays used in expressions with rare exceptions are converted to pointers to their first elements.
From the C++ 17 Standard (7.2 Array-to-pointer conversion)
Consider the following demonstration program.
Its output might loop like
As it is seen from the output the array designator
arr
was converted to a pointer in the expressionarr + 0
.The same way if an array is used as an argument expression and the corresponding parameter type is not a referenced type when the array is converted to a pointer to its first element.
There is no constructor in the class template
std::vector
that has the first parameter having a referenced type to an array.But there is a template constructor that accepts two first arguments of the same type
So in this declaration
there is used two above constructor where two first arguments are converted to pointers of the type
int *
.Pointers have the same operations as a random access iterator. Thus the vector is created using the range of integer values
[arr, arr + sizeof( arr ) / sizeof( arr[0] )
As for this expression
then the expression &a has the type
int ( * )[5]
that points to the array a.. The expression&a + 1
points to the address pass the last element of the array. The dereferenced expression *(&a + 1) has the type int[5] that denotes an array that again used as an expression is converted to pointer of the typeint *
.So you have in fact two expressions of the type
int *
in this declarationHowever this approach is not correct because you may not dereference a pointer that points after a valid object.
第一部分有几个错误:
正确的版本是:
其中
arr
加上“arr
中的元素数量”是刚刚经过arr 末尾的指针
。在第二部分中,
*(&a + 1)
是一个指针。&a
是一个指向a
的指针,它是一个由 5 个整数组成的数组。因此,加 1 会使指针sizeof(a)
字节增加(整数大小的 5 倍)。因此,结果再次是一个刚刚经过a
末尾的指针,因此向量是用a
的元素初始化的。The first piece has several errors:
The correct version would be:
where
arr
plus "the number of elements inarr
" is a pointer just past the end ofarr
.In the second piece,
*(&a + 1)
, is a pointer.&a
is a pointer toa
which is an array of 5 integers. Thus adding 1 advances the pointersizeof(a)
bytes (5 times the size of an integer). Hence, again the result is a pointer just past the end ofa
and thus the vector is initialized with the elements ofa
.