为啥我不能在 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&lt;int, 3&gt; *是什么吗? 我相信更好的解决方案是改用void function(array&lt;int,3&gt; &amp; ptr) 【参考方案1】:

由于ptr是指向std::array的指针,所以你应该先得到std::array,然后才能使用operator[],否则你在指针上使用operator[],这不是一样的

【讨论】:

【参考方案2】:

指针只是一个数字(内存地址),指向别的东西。它没有[] 运算符(即使指向的东西 可能有)。您需要取消引用指针以获取它指向的东西,然后如果该东西支持它,您可以使用[]

【讨论】:

【参考方案3】:
    int *a = new int[3];
    a[2];

由于aint *a[2]int

    void function(array<int,3> * ptr)
    
        int temp = ptr[2]; // Error

由于ptrarray&lt;int,3&gt; *ptr[2]array&lt;int,3&gt;。那么这个任务怎么做呢?

【讨论】:

【参考方案4】:

您正在处理指针运算

function() 内部,您有一个std::array&lt;int,3&gt;* 指向std::array 对象数组的指针(在您的示例中,&amp;arr 可以被视为指向1 个std::array 对象数组的指针)。

将索引偏移量应用于类型化指针将使指针前进一个字节数,该字节数等于索引乘以所指向的类型的大小。

所以,给定ptr 是一个std::array&lt;int,3&gt;* 指针,那么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)
  )
)

这就是为什么当ptrstd::array&lt;int,3&gt;* 指针时int temp = ptr[2]; 不起作用。取消引用ptr 将为您提供std::array&lt;int,3&gt;&amp; 引用,而不是int(请注意,在您的示例中,ptr 指向单个std::array,因此ptr[2] 越界,但@987654341 @ 和 *ptr 将起作用,因为它们与 *(ptr+0) 相同。

这就是为什么当aint* 指针时int temp = a[2]; 确实有效。取消引用 a 将为您提供 int&amp; 引用。

要访问位于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】:

这个问题的另一个解决方案是使用&amp; 运算符。它消除了很多不确定性。

#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&lt;int,3&gt; * 可以用作array&lt;int,3&gt; 数组的迭代器。当您通过此类指针间接时,您不会获得int

您尚未创建array&lt;int,3&gt; 的数组。您已经创建了一个array&lt;int,3&gt;ptr[2] 索引处没有 array&lt;int,3&gt; 对象。

【讨论】:

指向 any 变量的指针可以被视为指向包含 1 个元素的数组的指针。因此,给定 OP 的原始代码中的 array&lt;int,3&gt; arr=1,2,3; function(&amp;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>() 似乎是

我不知道为啥我不能在 C++ 中初始化一个数组的数组

为啥我可以从 初始化常规数组,而不是 std::array

为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?

我应该如何大括号初始化 std::pairs 的 std::array?

如何从方法返回静态 const int std::array?