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:将类成员变量编号从非静态更改为静态
答案 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
引用堆栈上的变量。如果您更改了更改,则更改将存储在已分配localObj
中main
的堆栈中。
当您致电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
中