現在、「独習C++」という書籍を使用しC++を独学で勉強しています。この書籍の中でメモリの動的確保の節の例題プログラム中で、不明点があり質問させて頂きました。以下に例題プログラムを記します。

#include "stdafx.h"
#include "iostream"

using namespace std;

int main()
{
int *p;

p = new int[5];     //5つの整数用のメモリを割り当てる

//割り当ての成功を確認
if (!p) {
    cout << "メモリの割り当てエラー" << endl;
    return 1;
}

int i;

for (i = 0; i < 5; i++) {
    p[i] = i;                    //※1
}

for (i = 0; i < 5; i++) {
    cout << "整数型p[" << i << "]は:";
    cout << p[i] << endl;         //※2
}

delete[] p; //メモリの解放

return 0;
}

 プログラム中の※1,※2で、それぞれ動的に確保したint型ポインタに値の格納と値の表示が行われています。ここで、私が疑問に思っているのはなぜ間接参照演算子*を使用せずにポインタ変数に値を代入できているのか?p[i]はアドレスを格納する変数なのではないか?ということです。私が思うに、※1の部分は

*(p + i) = i;

※2の部分は

cout << *(p + i) << endl;

と書くべきなのではないかと思います。
 しかし、実際に両方の構文を試してみると、どちらの書き方でもプログラムは正常に動作しました。何故ポインタ変数に直接的に値を格納するような書き方(p[i] = i;)ができるのか。これをどのように解釈すればよいか悩んでいます。初歩的な質問ですが、ご回答いただければ幸いです。
よろしくお願いいたします。