7

Q1。在Java中,所有的对象、数组和类变量都存储在堆上?C++ 也一样吗?数据段是堆的一部分吗?

那么下面的 C++ 代码呢?

class MyClass{
    private:
            static int counter; 
            static int number;
};

MyClass::number = 100;

Q2。据我了解,编译器赋予特定值的变量存储在数据段中,未初始化的全局和静态变量存储在 BSS(由符号启动的块)中。在这种情况下,静态的 MyClass::counter 被编译器初始化为零,因此它存储在 BSS 中,初始化为 100 的 MyClass::number 存储在数据段中。我的结论正确吗?

Q3。考虑以下代码:

void doHello(MyClass &localObj){   
// 3.1 localObj is a reference parameter, where will this get stored in Heap or Stack?
      // do something
}

void doHelloAgain(MyClass localObj){   
// 3.2 localObj is a parameter, where will this get stored in Heap or Stack?
      // do something
}

int main(){
      MyClass *a = new MyClass();  // stored in heap

      MyClass localObj;   
      // 3.3 Where is this stored in heap or stack?
      doHello(localObj);
      doHelloAgain(localObj);
}

我希望我已经把我的问题告诉了所有人

编辑:

关于BSS的一些了解请参考这篇文章

EDIT1:将类名从 MyInstance 更改为 MyClass,因为它是一个糟糕的名字。真诚的歉意

EDIT2:将类成员变量编号从非静态更改为静态

4

5 回答 5

6

这有点简化,但据我所知大部分是准确的。

在 Java 中,所有对象都分配在堆上(包括所有成员变量)。大多数其他东西(参数)是引用,并且引用本身与本机类型(ints,longs等)一起存储在堆栈中,除了字符串,它更像是一个对象而不是本机类型。

在 C++ 中,如果您要使用“new”关键字分配所有对象,这与 java 的情况几乎相同,但在 C++ 中有一种独特的情况,因为您可以在堆栈上分配对象(您并不总是必须使用“新”)。

另请注意,Java 的堆性能比 C 的堆性能更接近 C 的堆栈性能,垃圾收集器做了一些非常聪明的事情。它仍然不如堆栈好,但比堆好得多。这是必要的,因为 Java 不能在堆栈上分配对象。

于 2009-08-26T18:23:35.400 回答
2

第一季度

Java 也将变量存储在堆栈上,但类实例是在堆上分配的。在 C++ 中,您可以在堆栈或堆上自由分配您的类实例。通过使用new关键字,您可以在堆上分配实例。

数据段不是堆的一部分,而是在进程启动时分配的。堆用于动态内存分配,而数据段是静态的并且内容在编译时是已知的。

BSS 段只是一种优化,其中属于数据段的所有未初始化或初始化为零的数据(例如字符串、常数等)都被移动到 BSS 段。数据段必须嵌入到可执行文件中,并且通过将“所有零”移动到末尾,它们可以从可执行文件中删除。当加载可执行文件时,BSS 段被分配并初始化为零,编译器仍然能够知道 BSS 段内的各种缓冲区、变量等的地址。

第二季度

MyClass::number存储在MyClass分配类实例的位置。它可以在堆上或堆栈上。请注意在 Q3 中如何a指向MyClass在堆上分配的实例,而localObj在堆栈上分配。因此a->number位于堆上,而localObj.number位于堆栈上。

作为MyClass::number实例变量,您不能像这样分配它:

MyClass::number = 100;

但是,您可以分配MyClass::counter它是静态的(除了它是私有的):

MyClass::counter = 100;

第三季度

当您调用doHello变量localObj(in main) 时,它是通过引用传递的。localObjin变量doHello引用回堆栈上的该变量。如果更改它,更改将存储在分配localObjin的堆栈中。main

当您调用doHelloAgain变量localObj(in main) 时,它会被复制到堆栈中。内部doHelloAgain变量localObj分配在堆栈上,并且仅在调用期间存在。

于 2009-08-26T18:13:55.950 回答
1

此处列出了 C++ 中的所有内存区域

于 2009-08-26T19:52:27.060 回答
1

Q1。在Java中,所有的对象、数组和类变量都存储在堆上?C++ 也一样吗?数据段是堆的一部分吗?

不,数据部分与堆是分开的。基本上,数据部分是在加载时分配的,之后所有的东西都有一个固定的位置。此外,可以在堆栈上分配对象。

对象在堆上的唯一情况是使用new关键字,或者使用malloc函数族中的某些东西。

Q2。据我了解,编译器赋予特定值的变量存储在数据段中,未初始化的全局和静态变量存储在 BSS(由符号启动的块)中。在这种情况下,静态的 MyInstance::counter 被编译器初始化为零,因此它存储在 BSS 中,初始化为 100 的 MyInstance::number 存储在数据段中。我的结论正确吗?

是的,您对 BSS 部分的理解是正确的。但是,由于number代码不是静态的:

MyInstance::number = 100;

是不合法的,它需要被设为静态或在构造函数中正确初始化。如果在构造函数中初始化它,它就会存在于分配拥有对象的任何位置。如果将其设为静态,它将最终出现在数据部分......如果在任何地方。通常static const int变量可以直接内联到使用的代码中,这样根本不需要全局变量。

Q3。考虑以下代码:...

void doHello(MyInstance &localObj){

localObj 是对传递对象的引用。据你所知,没有存储,它是指被传递的变量在哪里。实际上,在后台,可以在堆栈上传递一个指针来促进这一点。但是如果可以的话,编译器也可以很容易地优化它。

void doHelloAgain(MyInstance localObj){

传递的参数的副本被放置在堆栈上。

MyInstance localObj;
// 3.3 Where is this stored in heap or stack?

localObj 在堆栈上。

于 2009-08-26T18:14:57.990 回答
1

在 C++ 中,可以在堆栈上分配对象……例如,在 Q3 主例程中的 localObj。

我感觉到关于类与实例的一些混淆。“MyInstance”作为变量名比作为类名更有意义。在您的 Q1 示例中,“数字”存在于 MyInstance 类型的每个对象中。“计数器”由所有实例共享。"MyInstance::counter = 100" 是一个有效的赋值,但 "MyInstance::number = 100" 不是,因为你没有指定哪个对象应该有它的 "number" 成员。

于 2009-08-26T18:20:09.213 回答