8

更正:

我把指针地址的概念和指针指向的地址搞混了,所以修改了下面的代码。现在它打印出我想要的内容,变量 a、c、i、j、k、p 在堆栈上,变量 b、d 在堆上。静态和全局变量在另一个段上。非常感谢你们!


好吧,我知道这两个概念被深入讨论了......但是我仍然对以下代码有疑问:

#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 中的两个静态变量 l 和 m 之外,所有其他变量的地址似乎都在一起。(注:代码和结果已被修改,与这里所说的不符。)

我已经搜索了很多关于堆栈和堆的信息。常识是,如果一个对象是由“new”创建的,那么它就在堆上。并且局部变量(例如上面示例中的 j 和 k)在堆栈上。但在我的示例中似乎并非如此。它取决于不同的编译器,还是我的理解是错误的?

非常感谢你们所有人。

4

8 回答 8

15

你的理解是错误的。例如,b是一个指针——如果你想要创建的对象的地址new,你需要打印出来b,而不是&bb是一个局部变量,因此它本身(位于&b)位于堆栈中。

对于您的示例,N,lm可能位于可执行文件的数据部分中的某个位置。如您所见,它们具有相似的地址。您要打印的每个其他变量都在堆栈中 - 它们的地址同样彼此相似。其中一些是指向从堆分配的对象的指针,但是您的打印输出都不会显示这一点。

于 2010-08-19T20:41:21.437 回答
3

你的理解是正确的。

  • 局部变量在栈上分配。
  • 动态分配的对象是在堆上分配的。

尽管您在示例中始终采用局部变量的地址。
示例:打印出d不是d. Asd是一个局部变量(所以地址类似于c),但它是一个指针变量,指向一个动态分配的对象(that is on the heap)

编译器如何实现堆栈和堆会有所不同。

在现代操作系统中,堆栈和堆甚至可以共享相同的区域(即您可以通过在堆中分配块来实现堆栈)。

于 2010-08-19T20:42:56.747 回答
2

如果要打印任何d指向的地址(在这种情况下,它指向堆上的一个对象),请执行

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

这将打印指针的值,指针的值是它指向的对象的地址。

你的代码有

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

这将打印 的地址d,正如您d在 main 中定义的那样,它将在堆栈上,您正在打印指针的地址。有指针本身和它指向的对象,它们是两个独立的东西,有不同的地址。

于 2010-08-19T20:42:55.450 回答
2

The only ones that are not 'together' in your example are l, m and N. They are two statics and one global, therefore they are not allocated on the stack for sure. They aren't from a heap neither, most likely, they are from a .data segment of your module. The only one from a heap should be the address b points to, but you're printing the address of b itself, not what it points to.

于 2010-08-19T20:44:39.723 回答
0

从纯 C++ 的角度来看,这两种形式之间的区别仅与对象生命周期的管理方式有关。

从这里开始,好好读

于 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

One may not safely assume anything about the relative addresses of things in the stack relative to those on the heap nor, for that matter, the relative addresses of any pointers that are not all derived from the same array or allocated (via malloc, calloc, etc.) block. I'm not even sure pointers are required to be rankable.

于 2010-08-19T21:11:50.180 回答