为啥我不能在 std::array< int, 3 > 的指针上使用运算符 [] 来索引值?
Posted
技术标签:
【中文标题】为啥我不能在 std::array< int, 3 > 的指针上使用运算符 [] 来索引值?【英文标题】:Why I cannot use the operator [] on a pointer of std::array< int, 3 > to index value?为什么我不能在 std::array< int, 3 > 的指针上使用运算符 [] 来索引值? 【发布时间】:2020-09-03 17:22:30 【问题描述】:代码:
void function(array<int,3> * ptr)
int temp = ptr[2]; // Error
int temp = (*ptr)[2]; // Can work!
int main(void)
array<int,3> arr=1,2,3;
function(&arr);
return 0;
我不知道为什么指针不能这样工作:
int *a = new int[3];
a[2];
感谢您的回答。
【问题讨论】:
你知道array<int, 3> *
是什么吗?
我相信更好的解决方案是改用void function(array<int,3> & ptr)
。
【参考方案1】:
由于ptr
是指向std::array
的指针,所以你应该先得到std::array
,然后才能使用operator[]
,否则你在指针上使用operator[]
,这不是一样的
【讨论】:
【参考方案2】:指针只是一个数字(内存地址),指向别的东西。它没有[]
运算符(即使指向的东西 可能有)。您需要取消引用指针以获取它指向的东西,然后如果该东西支持它,您可以使用[]
。
【讨论】:
【参考方案3】: int *a = new int[3];
a[2];
由于a
是int *
,a[2]
是int
。
void function(array<int,3> * ptr)
int temp = ptr[2]; // Error
由于ptr
是array<int,3> *
,ptr[2]
是array<int,3>
。那么这个任务怎么做呢?
【讨论】:
【参考方案4】:您正在处理指针运算。
在function()
内部,您有一个std::array<int,3>*
指向std::array
对象数组的指针(在您的示例中,&arr
可以被视为指向1 个std::array
对象数组的指针)。
将索引偏移量应用于类型化指针将使指针前进一个字节数,该字节数等于索引乘以所指向的类型的大小。
所以,给定ptr
是一个std::array<int,3>*
指针,那么ptr[N]
(与*(ptr + N)
相同)与做的一样:
*(
reinterpret_cast< std::array<int,3>* >(
reinterpret_cast<uintptr_t>(ptr)
+
(sizeof( std::array<int,3> ) * N)
)
)
或者,更一般地说:
*(
reinterpret_cast< decltype(ptr) >(
reinterpret_cast<uintptr_t>(ptr)
+
(sizeof( decltype(*ptr) ) * N)
)
)
这就是为什么当ptr
是std::array<int,3>*
指针时int temp = ptr[2];
不起作用。取消引用ptr
将为您提供std::array<int,3>&
引用,而不是int
(请注意,在您的示例中,ptr
指向单个std::array
,因此ptr[2]
越界,但@987654341 @ 和 *ptr
将起作用,因为它们与 *(ptr+0)
相同。
这就是为什么当a
是int*
指针时int temp = a[2];
确实有效。取消引用 a
将为您提供 int&
引用。
要访问位于std::array*
指针指向的数组的给定索引处的std::array
对象的特定int
元素,您必须首先取消引用该指针才能访问std::array
,并且那么你可以单独调用 its operator[]
,例如:
std::array<int,3> arr = 1,2,3;
std::array<int,3> *ptr = &arr; // arr is equivalent to an array of 1 element
int temp = ptr[0][2]; // same as (*ptr).operator[](2)
【讨论】:
【参考方案5】:这个问题的另一个解决方案是使用&
运算符。它消除了很多不确定性。
#include<iostream>
#include <array>
void function(std::array<int, 3>& arr1)
int temp = arr1[2];
int main()
std::array<int, 3> arr = 1,2,3;
function(arr);
return 0;
【讨论】:
虽然有用,但实际上并不能回答 OP 的问题。 @RemyLebeau 好的,我会删除它。这似乎是一个更好的解决方案。 当然,它更好,但它有助于解释为什么原始代码不起作用,以及为什么这个解决方案更好。【参考方案6】:指针是指向类型的数组的迭代器。
int*
可用作int
数组的迭代器。当你通过这样的指针间接时,你会得到一个int
。
array<int,3> *
可以用作array<int,3>
数组的迭代器。当您通过此类指针间接时,您不会获得int
。
您尚未创建array<int,3>
的数组。您已经创建了一个array<int,3>
。 ptr[2]
索引处没有 array<int,3>
对象。
【讨论】:
指向 any 变量的指针可以被视为指向包含 1 个元素的数组的指针。因此,给定 OP 的原始代码中的array<int,3> arr=1,2,3; function(&arr);
,那么 ptr[0]
将有效地访问 array
本身(不是 array
的第一个元素,而是 ptr[0][0]
),但 ptr[2]
无效。
@RemyLebeau 确实,虽然我认为提到这可能会进一步混淆 OP。以上是关于为啥我不能在 std::array< int, 3 > 的指针上使用运算符 [] 来索引值?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是
为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?