8

修正:

ポインタアドレスとポインタが指すアドレスの概念をめちゃくちゃにしてしまったので、以下のコードを修正しました。そして今、私が望むものを出力します。変数a、c、i、j、k、pはスタック上にあり、変数b、dはヒープ上にあります。静的変数とグローバル変数は別のセグメントにあります。皆様、どうもありがとうございました!


これら 2 つの概念が深く議論されていることは知っていますが、次のコードについてはまだ疑問があります。

#include <iostream>
using namespace std;

class A {

};

int N = 10;

void f(int p) {
    int j = 1;
    float k = 2.0;
    A c;
    A* d = new A();
    static int l = 23;
    static int m = 24;
    cout << "&c: " << &c << endl;
    cout << "&d: " << d << endl;
    cout << "&j: " << &j << endl;
    cout << "&k: " << &k << endl;
    cout << "&l: " << &l << endl;
    cout << "&m: " << &m << endl;
    cout << "&p: " << &p << endl;
}

int main() {
    int i = 0;
    A* a;
    A* b = new A();
    cout << "&a: " << &a << endl;
    cout << "&b: " << b << endl;
    cout << "&i: " << &i << endl;
    cout << "&N: " << &N << endl;
    f(10);
    return 0;
}

私の結果は次のとおりです。

&a: 0x28ff20
&b: 0x7c2990
&i: 0x28ff1c
&N: 0x443000
&c: 0x28fef3
&d: 0x7c0f00
&j: 0x28feec
&k: 0x28fee8
&l: 0x443004
&m: 0x443008
&p: 0x28ff00

これは非常に興味深いことです。なぜなら、グローバル変数 N と、関数 f の 2 つの静的変数 (l と m) を除いて、他のすべての変数のアドレスが一緒になっているように見えるからです。(注: コードと結果は変更されており、ここに記載されている内容とは一致しません。)

スタックとヒープについてよく調べました。「new」でオブジェクトを作成した場合、それはヒープ上にあるというのが常識です。また、ローカル変数 (上記のサンプルの j や k など) はスタックにあります。しかし、私の例ではそうではないようです。それは異なるコンパイラに依存していますか、それとも私の理解が間違っていますか?

皆様、どうもありがとうございました。

4

8 に答える 8

15

あなたの理解は間違っています。たとえば、bはポインタです。によって作成されたオブジェクトのアドレスが必要な場合は、ではなくnew、を出力する必要があります。 はローカル変数であるため、それ自体(で見つかります)はスタック上にあります。b&bb&b

あなたの例でNl、、、、mはおそらく実行可能ファイルのデータセクションのどこかにあります。ご覧のとおり、アドレスは似ています。印刷する他のすべての変数はスタック上にあります-それらのアドレスは同様に互いに類似しています。それらのいくつかは、ヒープから割り当てられたオブジェクトを指すポインターですが、どのプリントアウトにもそれは示されません。

于 2010-08-19T20:41:21.437 に答える
3

あなたの理解は正しいです。

  • ローカル変数はスタックに割り当てられます。
  • 動的に割り当てられたオブジェクトはヒープに割り当てられます。

あなたの例では一貫してローカル変数のアドレスを取得していますが。例:の住所ではなく
印刷します。はローカル変数 (アドレスは に似ています) ですが、動的に割り当てられたオブジェクトを指すポインター変数です。dddc(that is on the heap)

ただし、コンパイラがスタックとヒープを実装する方法は異なります。

最新の OS では、スタックとヒープが同じ領域を共有する場合もあります (つまり、ヒープにチャンクを割り当てることでスタックを実装できます)。

于 2010-08-19T20:42:56.747 に答える
2

d指しているアドレス(この場合はヒープ上のオブジェクトを指している)のアドレスを出力したい場合は、次のようにします。

  cout << "d: " << d << endl;

これにより、ポインターの値が出力されます。ポインターの値は、ポインターが指すオブジェクトのアドレスです。

あなたのコードは

   cout << "&d: " << &d << endl;

dmain 内で定義したように、これは のアドレスを出力しますd。これはスタック上にあり、ポインタのアドレスを出力しています。ポインター自体と、ポインターが指すオブジェクトがあります。これらは、別々のアドレスを持つ 2 つの別々のものです。

于 2010-08-19T20:42:55.450 に答える
2

あなたの例で「一緒に」ではない唯一のものはlmNです。これらは 2 つのスタティックと 1 つのグローバルであるため、確実にスタックに割り当てられません。それらはヒープからではなく、モジュールの .data セグメントからのものである可能性が最も高いです。bヒープからの唯一のものはアドレスが指しているはずですが、それが指しているアドレスでbはなく、それ自体のアドレスを出力しています。

于 2010-08-19T20:44:39.723 に答える
0

純粋な C++ の観点から見た 2 つの形式の違いは、オブジェクトの有効期間の管理方法だけです。

ここから、よく読んでください

于 2010-08-19T20:43:09.780 に答える
0

静的変数はデータ セグメントにあります。また、ポインタのアドレスとその値を混在させます。たとえば、次のとおりです。

a は、スタック上の A* 型のローカル変数です。&a は、(スタック上で) 実際に存在するアドレスも示します。a の値は、タイプ A のヒープ オブジェクトのアドレスです。

于 2010-08-19T20:44:05.307 に答える
0

さまざまなコンパイラが同じように動作することに依存することはできません。ほとんどすべてのコードについて、スタックとヒープの区別は無意味です。ご心配なく。

于 2010-08-19T20:44:16.277 に答える
0

スタック内のものとヒープ上のものとの相対アドレスについて安全に想定することはできません。さらに言えば、すべてが同じ配列から派生したものではない、または割り当てられた (malloc、calloc、など)ブロックします。ランク付けできるようにするためにポインターが必要かどうかさえわかりません。

于 2010-08-19T21:11:50.180 に答える