1

これは私には意味をなさないトピックの1つです。クラスのデータメンバーへのポインタを宣言して使用できます。でも、

  1. アイデアをサポートするロジックは何ですか?[私は構文について話しているのではなく、この機能のロジックについて話している]

  2. また、これを正しく理解している場合、これは、ポインターの初期化時に割り当てられるメモリの量が不定/可変であることを意味します。これは、その時点で任意の数のオブジェクトが存在する可能性があるためです。また、実行時に新しいオブジェクトが作成および破棄される場合があります。したがって、事実上、単一のステートメントによって多数の割り当て/割り当て解除が発生します。これは、他の言語と比較すると、かなり直感に反しているようです。それとも、これについての私の理解は間違っていますか?これほど広くプログラムの実行に暗黙的に影響を与える単一の初期化ステートメントは他にないと思います。

  3. 最後に、これらのポインタにメモリはどのように割り当てられますか?それらはオブジェクトに関してどこに配置されますか?これらのポインタの物理メモリアドレスを確認することは可能ですか?

4

3 に答える 3

3

データメンバーへのポインタの単一の宣言は、そのクラスのすべてのオブジェクトへのポインタを作成します。

いいえ、違います。メンバーへのポインターは、ポインターとは大きく異なる特別なオブジェクトです。オフセットによく似ています。クラスのオブジェクトへのポインタとメンバーポインタを指定すると、メンバーの値を取得できます。クラスのオブジェクトへのポインタがないと、メンバーへのポインタは役に立ちません。

質問2と3は、同じ基本的な誤解から生じています。

于 2012-09-05T15:23:43.693 に答える
2

データメンバーへのポインタの単一の宣言は、そのクラスのすべてのオブジェクトへのポインタを作成します。

いいえ。メンバーへのポインターを作成します(これは、オブジェクトのベースからのオフセットと見なす
ことができます)。次に、オブジェクトへのポインターと一緒に使用して、そのメンバーを取得できます。

struct S
{
    int  x;
    int  y;
};

int S::*  ptrToMember = &S::x;  // Pointer to a member.

S   obj;
int*      ptrToData   = &obj.x; // Pointer to object
                                // that happens to be a member

メンバーへのポインターを作成する際には、オブジェクトを使用しないことに注意してください(タイプ情報のみを使用します)。したがって、このポインターは、特定のメンバーを取得するためのクラスへのオフセットです。

ポインタまたはオブジェクトを介してデータメンバーにアクセスできます。

(obj.*ptrToMember)   = 5;   // Assign via pointer to member (requires an object)
*ptrToData           = 6;   // Assign via pointer already points at object.

クラスの特定のインスタンスを1つだけ指すように単一のポインターが作成されるのとは対照的に、これが発生するのはなぜですか?

それはポインタと呼ばれます。
類似しているが並列の概念(上記を参照)。

アイデアをサポートするロジックは何ですか?

愚かな例:

 void addOneToMember(S& obj, int S::* member) { (obj.*member) += 1; }

 void addOneToX(S& obj)    { addOneToMember(obj, &Obj::x);}
 void addOneToY(S& obj)    { addOneToMember(obj, &Obj::y);}

また、これを正しく理解している場合、これは、ポインターの初期化時に割り当てられるメモリの量が不定/可変であることを意味します。これは、その時点で任意の数のオブジェクトが存在する可能性があるためです。

いいえ。メンバーへのポインタは、オブジェクトへの単なるオフセットであるためです。値を取得するには、実際のオブジェクトが必要です。

最後に、これらのポインタにメモリはどのように割り当てられますか?

他のオブジェクトと同じように。レイアウトに関しては特別なことは何もありません。
ただし、実際のレイアウトは実装によって定義されます。したがって、コンパイラを参照せずにこの質問に答える方法はありません。しかし、それは本当にあなたには役に立たない。

これらのポインタの物理メモリアドレスを確認することは可能ですか?

もちろん。それらは他のオブジェクトと同じです。

 // Not that this will provide anything meaningful.
 std::cout.write(reinterpret_cast<char*>(&ptrToMember), sizeof(ptrToMember));

 // 1) take the address of the pointer to member.
 // 2) cast to char* as required by write.
 // 3) pass the size of the pointer to member 

 // and you should write the values printed out.
 // Note the values may be non printable but I am sure you can work with that
 // Also note the meaning is not useful to you as it is compiler dependent.
于 2012-09-05T16:17:05.727 に答える
0

内部的には、仮想ベースを持たないクラスの場合、メンバーデータへのポインターは、そのタイプのオブジェクトの先頭からのデータメンバーのオフセットを保持する必要があります。仮想ベースでは、最も派生したオブジェクトのタイプに応じて仮想ベースの場所が変わる可能性があるため、少し複雑になります。とにかく、関連するデータは少量であり、データメンバーへのポインタを逆参照すると、コンパイラはそれにアクセスするための適切なコードを生成します。

于 2012-09-05T15:23:04.443 に答える