数组可以在 c++ 中用作迭代器吗?

发布于 2025-01-11 14:28:36 字数 341 浏览 0 评论 0原文

我只是浏览 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

和我恋爱吧 2025-01-18 14:28:36
int arr[5] = [1,2,3,4,5]
std::vector v(arr, arr + arr.size()/arr[0])

为什么会这样?

这是行不通的。

那么数组也是一个迭代器吗?

数组不是迭代器。但是数组可以隐式转换为指向第一个元素的指针,该元素是数组的迭代器。


int a[5] = {0, 1, 2, 3, 4};
矢量 v4(a, *(&a + 1));

这到底是做什么的

是一种不必要的复杂书写方式:

std::vector<int> v4(std::begin(a), std::end(a));
int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])

Why does this work?

This doesn't work.

So is an array just an iterator as well?

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.


int a[5] = {0, 1, 2, 3, 4};
vector<int> v4(a, *(&a + 1));

What exactly is this doing

This is an unnecessarily complex way of writing:

std::vector<int> v4(std::begin(a), std::end(a));
温柔一刀 2025-01-18 14:28:36
int arr[5];

int *begin=arr;
int *end=arr+sizeof(arr)/sizeof(*arr);

std::vector<int> v(begin, end);

这里的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

int arr[5];

int *begin=arr;
int *end=arr+sizeof(arr)/sizeof(*arr);

std::vector<int> v(begin, end);

Here arr (as in begin=arr) is a "pointer", which can be used like an iterator. So begin=arr is an "iterator" to the beginning of the array and end 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[] or int* 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.

我也只是我 2025-01-18 14:28:36

对于初学者来说,有一个拼写错误,

int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])

您的意思似乎是

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + sizeof( arr ) / sizeof( arr[0] ));

虽然如果您的编译器支持 C++ 17,您可以编写

#include <iterator>

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + std::size( arr ));

在具有罕见异常的表达式中使用的数组将转换为指向其第一个元素的指针。

来自 C++ 17 标准(7.2 数组到指针的转换)

1 “NT 数组”或“未知数组”类型的左值或右值
T 的界限”可以转换为“指向 T 的指针”类型的纯右值。这
应用临时物化转换(7.4)。结果是
指向数组第一个元素的指针。

考虑以下演示程序。

#include <iostream>

int main()
{
    int arr[5] = { 1, 2, 3, 4, 5 };

    std::cout << "sizeof( arr ) = " << sizeof( arr ) << '\n';
    std::cout << "sizeof( arr + 0 ) = " << sizeof( arr + 0 ) << '\n';
}

循环

sizeof( arr ) = 20
sizeof( arr + 0 ) = 4

它的输出可能会像从输出中看到的那样

,数组指示符arr被转换为表达式arr + 0中的指针。如果将数组用作参数表达式,并且当数组转换为指向其第一个元素的指针时,相应的参数类型不是引用类型,则同样的方式。

类模板 std::vector 中没有第一个参数具有数组引用类型的构造函数。

但是有一个模板构造函数接受相同类型的两个第一个参数,

template <class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

因此在此声明中

std::vector<int> v(arr, arr + sizeof( arr ) / sizeof( arr[0] ));

使用了两个上述构造函数,其中两个第一个参数转换为 int * 类型的指针。

指针与随机访问迭代器具有相同的操作。因此,向量是使用整数值范围 [arr, arr + sizeof( arr ) / sizeof( arr[0] ) 创建的

对于此表达式

*(&a + 1)

,则表达式 &a 的类型为 int ( * )[5] 指向数组 a.. 表达式&a + 1 指向数组最后一个元素的地址。解除引用的表达式 *(&a + 1) 的类型为 int[5],表示再次用作表达式的数组,该数组将转换为 int * 类型的指针。

因此,实际上在此声明中有两个 int * 类型的表达式。

vector<int> v4(a, *(&a + 1));

但是,这种方法并不正确,因为您可能无法取消引用指向有效对象的指针。

For starters there is a typo

int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])

It seems you mean

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + sizeof( arr ) / sizeof( arr[0] ));

Though if your compiler supports the C++ 17 you could write

#include <iterator>

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + std::size( arr ));

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)

1 An lvalue or rvalue of type “array of N T” or “array of unknown
bound of T” can be converted to a prvalue of type “pointer to T”. The
temporary materialization conversion (7.4) is applied. The result is a
pointer to the first element of the array.

Consider the following demonstration program.

#include <iostream>

int main()
{
    int arr[5] = { 1, 2, 3, 4, 5 };

    std::cout << "sizeof( arr ) = " << sizeof( arr ) << '\n';
    std::cout << "sizeof( arr + 0 ) = " << sizeof( arr + 0 ) << '\n';
}

Its output might loop like

sizeof( arr ) = 20
sizeof( arr + 0 ) = 4

As it is seen from the output the array designator arr was converted to a pointer in the expression arr + 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

template <class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

So in this declaration

std::vector<int> v(arr, arr + sizeof( arr ) / sizeof( arr[0] ));

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

*(&a + 1)

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 type int *.

So you have in fact two expressions of the type int * in this declaration

vector<int> v4(a, *(&a + 1));

However this approach is not correct because you may not dereference a pointer that points after a valid object.

暮倦 2025-01-18 14:28:36

第一部分有几个错误:

int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])

正确的版本是:

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

其中 arr 加上“arr 中的元素数量”是刚刚经过 arr 末尾的指针

在第二部分中,*(&a + 1) 是一个指针。 &a 是一个指向 a 的指针,它是一个由 5 个整数组成的数组。因此,加 1 会使指针 sizeof(a) 字节增加(整数大小的 5 倍)。因此,结果再次是一个刚刚经过 a 末尾的指针,因此向量是用 a 的元素初始化的。

The first piece has several errors:

int arr[5] = [1,2,3,4,5]
std::vector<int> v(arr, arr + arr.size()/arr[0])

The correct version would be:

int arr[5] = {1,2,3,4,5};
std::vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

where arr plus "the number of elements in arr" is a pointer just past the end of arr.

In the second piece, *(&a + 1), is a pointer. &a is a pointer to a which is an array of 5 integers. Thus adding 1 advances the pointer sizeof(a) bytes (5 times the size of an integer). Hence, again the result is a pointer just past the end of a and thus the vector is initialized with the elements of a.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文