3

私は(画像図を通して)ポインタを含む次の3つのコードステートメントを理解しようとしています。あなたがそれを説明することができれば、それもうまくいくだろう画像なしで

1- myobj *ptra = new myobj();
2- myobj *ptrb = new myobj[2]();
3- myobj **ptrc = new *myobj();

これが私の理解です。間違っている場合は訂正してください。また、画像内のアドレスは完全に架空のものです(意味がないことはわかっています)。私の理解に関する主な関心事は、基本的にステートメント2とステートメント3です。

ステートメント1:ptra(スタック上のアドレス)はヒープ上のアドレスを指します

ステートメント2:ptra(スタック上のアドレス)は、2つの部分からなる1つのアドレスを指しますか?あれは正しいですか ?

ここに画像の説明を入力してください

4

1 に答える 1

7

あなたの理解はやや正しいですが、あまりにも多くのものを混ぜ合わせているようで、図には詳細が欠けています。これが私が最も単純なケースのいくつかのためにそれを描く方法です...

new単純なケースから始めて、オペレーターを写真から外してみましょう。

#include <cstdio>

struct myobj {
    int v;
};

int main()
{
    myobj obj[2];

    obj[0].v = 1;
    obj[1].v = 2;

    myobj *ptra = &obj[0];
    myobj *ptrb = &obj[1];
    myobj **ptrc = &ptrb;

    printf("obj size is: %lu\n", sizeof(myobj));
    printf("pointer size: %lu\n", sizeof(void *));

    printf("obj[0] address: %p\n", (void *)&obj[0]);
    printf("obj[1] address: %p\n", (void *)&obj[1]);
    printf("ptra address is %p, it points to %p\n", (void *)&ptra, (void *)ptra);
    printf("ptrb address is %p, it points to %p\n", (void *)&ptrb, (void *)ptrb);
    printf("ptrc address is %p, it points to %p\n", (void *)&ptrc, (void *)ptrc);
}

上記のプログラムは次のようなものを出力します:

$ g++ -Wall -pedantic -o test ./test.cpp 
$ ./test 
obj size is: 4
pointer size: 8
obj[0] address: 0x7fff5b73dbc0
obj[1] address: 0x7fff5b73dbc4
ptra address is 0x7fff5b73dbb8, it points to 0x7fff5b73dbc0
ptrb address is 0x7fff5b73dbb0, it points to 0x7fff5b73dbc4
ptrc address is 0x7fff5b73dba8, it points to 0x7fff5b73dbb0

これは、メモリ内の次の単純なレイアウトに対応します。

シンプルなデータレイアウト

それで、あなたの絵と何が違うのですか?ポインタとオブジェクトのアドレス。ポインタ自体がアドレス0に配置されている場合、ポインタ自体がより多くのスペースを使用するという理由だけで次のポインタをアドレス1に配置できないため、他のデータは0 + sizeof(void*)アドレスにのみ配置できます。オブジェクトの場合、次のアドレスは、少なくともオブジェクト自体のサイズ(つまりsizeof(myobj))だけ大きくなります。

動的割り当てが関係する場合、状況は少し変わります。たとえば、演算子「new」を使用して次のようなオブジェクトを割り当てる場合:

myobj *ptra = new myobj();
myobj *ptrb = new myobj();
myobj **ptrc = &ptrb;

...次のようなメモリレイアウトを考えることができます。

動的メモリレイアウト

ここで、別のポインター(**)へのポインターは、オブジェクトを指す1つ以上のポインターの最初のものを指すポインターに他なりません。簡単ですよね?ポインタへのポインタを持つことができます...とにかく、次のように、ポインタへの動的に割り当てられたポインタを使用します。

myobj *ptra = new myobj();
myobj *ptrb = new myobj();
myobj **ptrc = new myobj*[2];
ptrc[0] = ptra;
ptrc[1] = ptrb;

メモリレイアウトは次のようになります。

ポインタへのポインタ付き

ちなみに、ここの3行目にエラーがあります- myobj **ptrc = new *myobj();。する必要がありますmyobj **ptrc = new myobj*();

myobj *ptrb = new myobj[2]();後の質問に対処するために、動的に割り当てられた2つのオブジェクトを指すポインターがある式の結果を示す図を以下に示します。ポインタ自体は、割り当てられた2つのうち最初のオブジェクトを指します。

myobj * ptrb = new myobj [2]();

そして、違いを確認できるように、ポインタへのポインタについてもう一度説明します。次のコードを検討してください。

struct myobj {
    int v;
};

int main()
{
    myobj *ptra = new myobj[2]();
    myobj *ptrb = new myobj[4]();
    myobj **ptrc = new myobj*[2];

    ptrc[0] = ptra;
    ptrc[1] = ptrb;

    ptrc[0][0].v = 1;
    ptrc[0][1].v = 2;
    ptrc[1][0].v = 3;
    ptrc[1][1].v = 4;
    ptrc[1][2].v = 5;
    ptrc[1][3].v = 6;
}

次のレイアウトが作成されます。

ここに画像の説明を入力してください

ご覧のとおり、スタックには動的に割り当てられていない3つのポインター(これらはオブジェクトでもあります)が含まれています。これは宣言の結果です:

myobj *ptra;
myobj *ptrb;
myobj **ptrc;

次に、3つの異なるものが「新規」で割り当てられます。

  1. タイプの2つのオブジェクトが式myobjで割り当てられnew myobj[2]()、それらのオブジェクトの最初のオブジェクトへのアドレスがポインタに格納されますptra
  2. タイプの4つのオブジェクトが式myobjで割り当てられnew myobj[4]()、その式の結果は4つのオブジェクトのうちの最初のアドレスであり、ポインター「ptrb」に格納されます。
  3. 2つのポインタが式で割り当てられますnew myobj*[2]。その式の結果は、2つのポインターのうちの最初のアドレスです。そのアドレスは変数に格納されますptrc

ここで、(「ブロックC」内の)これらの2つの割り当てられたポインターは、「どこにも」を指しません。ptraしたがって、例として、ptrbポインタを「値で」コピーすることで、同じオブジェクトをポイントし、ポイントしているようにします。

ptrc[0] = ptra;
ptrc[1] = ptrb;

とても簡単です!

于 2012-10-21T05:20:35.633 に答える