堆栈框架问题:Java与C ++

时间:2009-08-26 17:58:57

标签: c++ c stack heap

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

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);
}

我希望我已经向所有人提出了明确的问题

修改

请参阅此article以了解对BSS的一些了解

EDIT1:将类名从MyInstance更改为MyClass,因为它名声不佳。诚挚道歉

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

5 个答案:

答案 0 :(得分:6)

这有点简化,但据我所知最为准确。

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

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

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

答案 1 :(得分:2)

<强> Q1

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

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

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

<强> Q2

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

由于MyClass::number是一个实例变量,您不能像这样分配它:

MyClass::number = 100;

但是,您可以指定MyClass::counter,因为它是静态的(除非它是私有的):

MyClass::counter = 100;

<强> Q3

当您致电doHello时,变量localObj(在main中)通过引用传递。 localObj中的变量doHello引用堆栈上的变量。如果您更改了更改,则更改将存储在已分配localObjmain的堆栈中。

当您致电doHelloAgain时,变量localObj(在main中)被复制到堆栈中。在doHelloAgain内,变量localObj在堆栈上分配,仅在调用期间存在。

答案 2 :(得分:1)

  

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

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

对象在堆上的唯一时间是使用new关键字,或者使用malloc函数系列中的某些内容。

  

Q2。据我所知,   给定特定的变量   编译器的值存储在数据中   细分市场和非全球化的全球化和   静态变量存储在BSS中   (以符号开头的块)。在这   case,MyInstance :: counter是静态的   由编译器初始化为零   所以它存储在BSS和   MyInstance ::数字是   初始化为100存储在   数据段。我在制作中是否正确   结论?

是的,您对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在堆栈上。

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

C ++中的所有内存区都列在here