将C++数组转换为向量

4

我在Leetcode上找到以下代码。然而,我无法理解下面两行的含义,特别是*(&a + 1)。结果显示了一个数组a的副本。有谁能够解释一下吗?谢谢!

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

据我所知,a是指向第一个元素的指针,而&a给出指针的地址,那么我不明白(&a + 1)代表什么,以及地址*(&a + 1)是什么。我的猜测是,由于a已经定义了其大小,*(&a + 1)将指向数组的末尾? - user8822312
1
这里没有类型转换。 - M.M
@πάνταῥεῖ 为什么有人会写这个,大概是因为什么原因呢? - M.M
@doug 嗯,有很多明确定义且更易读的方法,“不需要知道数组的长度”,例如 vector<int> v4( std::begin(a), std::end(a) ); - M.M
@M.M 我同意这种写法更易读。但是 vector<int> v4(a, *(&a + 1)); 这样的写法也可以在旧版和新版的 C++ 中使用,并且对于 C++ 程序员而言应该是相当清晰的,因为它甚至不需要除了 vector 以外的库文件。但是对于新版的 C++ 而言我非常认同您的观点。这种写法还有一个优点,就是适用于不同的容器类型。然而,我仍然看到很多人明确地声明 vector 的构造方式,这种写法更糟糕。 - doug
显示剩余2条评论
2个回答

4

当你从数组构造向量时,通常遇到的示例如下所示:

int a[5] = {...};
vector<int> v4(a, a + 5 );
// or vector<int>(a, a+sizeof(a)/int); // automatically calculate num elems inside a

上面的示例展示了如何使用数组"a"中的所有元素来构造一个向量。在这个示例中,"a"只是数组起始元素的地址,然后你加上5得到最后一个元素的地址。更直观的写法是:

vector<int> v4(begin(a), end(a));

除非你不想在v4中拥有a的所有元素

现在,你给我们的例子是第一个例子的简写形式,在这种情况下,你不需要显式地指定数组的大小。我猜你只是对向量构造函数的第二个参数感到困惑。第二个参数只返回数组"a"的最后一个元素的地址。但是怎么做呢?

好吧,让我们来分解一下:&a返回"a[]"的地址。本质上是"a"数组的指针。现在,如果你在这个地址上加1,你将得到一个指向地址"a[0]" + sizeof a[] 的指针,它将指向地址a的最后一个元素。把这个与上面的第一个例子进行比较。你必须加5,为什么这里不是这样?因为你正在使用不同的单位。&a指向a[]的起始地址,而不是数组的第一个元素的地址。所以,你实际上是按照a[5]单位移动地址,而不是按照int单位移动。

最后,你有解引用运算符“*”来解引用指针并获取数组[]的最后一个元素的地址。

a是类型a[],&a是类型*a[],因此需要解引用才能使它们成为相同的类型,否则你会得到一个编译器错误。

简而言之,你正在使用不同的方法来获取最后一个元素的地址。+1运算符相对于你处理的类型而行事。 a + 1与"a"的起始地址加上1个整数的大小相同。 &a + 1与a[]的起始地址加上a[]的大小相同。


2
你被数组衰减所迷惑了。变量a代表整个数组,它在大多数情况下会衰减成指向第一个元素的指针,但是对于一元运算符&,它不会发生衰减。所以&a给出的是整个数组的地址,而不是第一个元素的地址。虽然它们指向同一位置,但它们的类型不同 (int (*)[5]int *),这种不同的类型会导致指针算术运算有所不同。"最初的回答"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接