0

ポインタをよく把握していると思った瞬間、また戸惑いました。あなたの洞察はおそらく役立つでしょう。

私は、次のように、非常に一般的な言葉で私を混乱させるものを述べることができると思います。

a)私が書いた場合A* p = new A(); (Aクラスはどこにありますか)そして、のようなことをすると、が(*p).do_stuff()指すオブジェクトpがメモリ内を移動する可能性があるのに、なぜpそれでも私のオブジェクトを指すのでしょうか?

b)クラスとクラスのメンバー変数はどのようにメモリに格納されますか。

しかし、私がもう少し具体的に持っている問題をあなたに話す方がもっと役に立つかもしれません。Carメンバー変数を持つクラスがあるとしますEngine engine_;Engine他のクラスはどこにありますか)。罰金。ここで、何らかの理由で、のポインタであるメンバー変数を持つクラスを作成したいとしますEngine

class Car
{
    friend Repair;
public:
    Car() {engine_ = Engine();}
private:
    Engine engine_;
};

class Repair
{
public:
    Repair(const Car &car) : engine_(&(car.engine_)) {}
private:
    Engine *engine_;
};

いつも私の車のエンジンを指す可能性はありませんrepair.engine_、ありますか(?)しかし、この2番目のバージョンでも:

class Car
{
    friend Repair;
public:
    Car() {engine_ = new Engine();}
    ~Car() {delete engine_;}
private:
    Engine *engine_;
};
// Maybe I need/should write consts somewhere, not sure

class Repair
{
public:
    Repair(const Car &car) : engine_(car.engine_) {}
private:
    Engine *engine_;
};

これが機能する可能性は高いようですが、どのように機能するか/理解できません...

よろしくお願いします!

4

4 に答える 4

2

私が書いた場合A* p = new A();(どこにAクラスがありますか)、次のようなこと(*p).do_stuff()をすると、 p が指すオブジェクトがメモリ内で移動する可能性があります

いいえ、そうはなりません。(少なくとも、*pそのままです。ポインター メンバー自体がある場合は、他の場所を指すようにリセットされる可能性があります。)

クラスとクラスのメンバー変数はどのようにメモリに格納されますか

ビットとして。

class Foo {
    int i;
    char *p;

  public:
     void bla();
};

int(おそらく 32) のビットとそれに続くポインター (32 または 64)のビットとして表され、その間にパディングが行われる可能性があります。メソッドはインスタンス内のスペースを占有せず、個別に保存されます。

あなたの例については、私は問題を正確に理解していません。オブジェクトが生きている限り、Carが生きていて、 がリセットされない場合は機能するはずです。(特に頑丈そうには見えませんが…)Engine*Repair

于 2012-06-27T18:02:50.857 に答える
0

で割り当てられたC++のポインタnewは移動しません。mallocポインタをrealloc'dして、結果として新しい場所に移動できる、を考えているかもしれません。

Bjarne Stroustrupは、C ++コンテナーは一般に、動的なサイズのメモリーが必要な場合に対処するためのより良い方法を提供すると感じました。

http://www2.research.att.com/~bs/bs_faq2.html#renew

メモリの移動と再編成を可能にするために、一部のシステムは、使用する前にポインタにロックする必要がある抽象ハンドルを使用します... Windowsなど:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366584(v=vs.85).aspx

ある種の定期的なメモリの最適化を行う必要があるシステムでは、ポインタにロックする抽象的なものを使用することが理にかなっている場合があります。ただし、C ++はデフォルトでその間接参照のコストを支払いません。そうすることが理にかなっている場合にのみ、C++を実装します。

(欠点として、100万個のオブジェクトを割り当ててから、999,999個のオブジェクトを削除すると、移動できないポインタが使用されます...残った1つのオブジェクトが、アドレス空間の上部に留まる可能性があります。OS/ページングシステムは次のとおりです。これを問題にするよりも賢いはずですが、アロケータがカスタムの場合、ヒープが大きなサイズのままになる可能性があります。たとえば、オブジェクトのバッキングストアとしてメモリマップトファイルを使用している場合。 。大きくてほとんど空のディスクファイルでスタックします。)

于 2012-06-27T18:12:03.753 に答える
0

ケース 1) とケース 2) の両方で、repair.engine_常にあなたの車を指すという保証はありません。これは、クラス 'Car' のメンバーではなく、フレンド クラスであるためです。

于 2012-06-27T18:08:10.763 に答える
0

他の人が言ったように、 のようなことをすると、オブジェクトはメモリ内で移動しません(*p).do_stuff();。ある時点で学んだことを誤解しているに違いありません。

2 番目の質問では、メンバー関数とメンバー変数がメモリ内の別の場所に格納されています。メンバー関数のコードは、クラスのインスタンスごとに 1 回ではなく、クラスごとに 1 回だけ生成されます。このコードは、メモリ内のある場所に保存されます。

メンバー変数に関しては、これは、オブジェクトのメモリ内の場所について言及するときに人々が話していることです。たとえば、次のようなクラスがある場合

class MyClass{
  private:
    int a;
    int b;
    double c;
  public:
    void fun();
};

そのインスタンスがメモリ位置 0x0000 に格納されていると仮定します。これaは、位置 0x0000、b が 0x0004、c が 0x0008 であることを意味します (または、メモリの配置方法によってはこのようなものになります)。関数fun()は完全に別の場所に保存されます。

の別のインスタンスを作成するとMyClass、そのa変数は 0x000C、b0x0010、および 0x0014 にある可能性がありますc。最後に、最初のインスタンスfun()とまったく同じ場所にあります。fun()

于 2012-06-27T18:10:50.307 に答える