C++ - インデックス値に std::array< int, 3 > のポインターで演算子 [] を使用できないのはなぜですか?

okwaves2024-01-25  10

コード:

    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];

ご回答いただきありがとうございます。

1

配列 が何か知っていますか? * は?

– user253751

2020 年 9 月 3 日 17:31

より良い解決策は void function(array<int,3> & を使用することだと思います)ptr) 代わりに。

– ドレッシャージム

2020 年 9 月 3 日 17:44



------------------------

ptr は std::array へのポインタであるため、最初に std::array を取得する必要があります。その後でのみ、operator[] を使用できます。そうでない場合は、ポインタに対して Operator[] を使用することになります。同じ



------------------------

ポインタは、それを参照する単なる数値 (メモリ アドレス) です。他のもの。 [] 演算子はありません (たとえ指すものに [] 演算子があったとしても)。ポインタが指すものを取得するには、ポインタを逆参照する必要があります。その後、そのものがサポートしている場合は [] を使用できます。



------------------------

    int *a = new int[3];
    a[2];

a は int * であるため、a[2] は int です。

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

ptr は配列であるため、 *、ptr[2] は配列 です。では、その割り当てはどのように機能するのでしょうか?

-------------------------------

ここではポインタ演算を扱っています。

function() の内部には、std::array オブジェクトの配列への std::array<int,3>* ポインタがあります (この例では、&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)
  )
)

これが、int temp = ptr[2]; である理由です。 ptr が std::array<int,3>* ポインタの場合は機能しません。 ptr を逆参照すると、 std::array& が得られます。 int ではなく参照 (例の注意)ptr は単一の std::array を指しているため、ptr[2] は範囲外ですが、ptr[0] と *ptr は *(ptr+0)) と同じであるため機能します。

これが int temp = a[2]; の理由です。 a が int* ポインタの場合に機能します。を逆参照すると、int&; が得られます。参照。

std::array* ポインタが指す配列の特定のインデックスにある std::array オブジェクトの特定の int 要素にアクセスするには、まずポインタを逆参照して std::array にアクセスする必要があります。その後、その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)



------------------------

この問題を解決するには、次のような方法があります。& を使用していることオペレーター。これにより、多くの不確実性が解消されます。

#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;
}

3

これは便利ですが、OP の質問に対する実際の答えにはなりません。

– レミー・ルボー

2020 年 9 月 3 日 22:06

@RemyLebeau わかりました、削除します。これはより良い解決策のように思えました。

– ジェノ C

2020 年 9 月 3 日 22:20

確かに、その方が優れていますが、元のコードが機能しない理由と、このソリューションが優れている理由を説明するのに役立ちます。

– レミー・ルボー

2020 年 9 月 3 日 22:39



------------------------

ポインタは、ポイントされた型の配列のイテレータです。

int* は、int の配列のイテレータとして使用できます。このようなポインタを介して間接的に実行すると、int が返されます。

配列 * iteraとして使用できますarray の配列の場合は tor。このようなポインタを介して間接的に実行すると、int は取得されません。

array<int,3> の配列を作成していません。配列 を 1 つだけ作成しました。配列はありません。 ptr[2] インデックスのオブジェクト。

2

任意の変数へのポインタは、1 要素の配列へのポインタとして扱うことができます。したがって、配列 が与えられると、 arr={1,2,3};関数(&arr); OP の元のコードでは、ptr[0] は配列自体 (配列の最初の e ではなく) にアクセスするのに有効です。要素の場合、代わりに ptr[0][0] になります)、しかし ptr[2] は無効になります。

– レミー・ルボー

2020 年 9 月 3 日 22:14

@RemyLebeau 確かに、そのことに言及するとOPがさらに混乱する可能性があると思います。

– エロリカ

2020 年 9 月 3 日 22:31

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。