堆栈帧问题:Java 与 C++
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 的一些了解
编辑1:将类名从 MyInstance 更改为 MyClass,因为它是一个糟糕的名称。真诚的道歉
编辑2:将类成员变量号从非静态更改为静态
Q1. In Java, all objects, arrays and class variables are stored on the heap? Is the same true for C++? Is data segment a part of Heap?
What about the following code in C++?
class MyClass{
private:
static int counter;
static int number;
};
MyClass::number = 100;
Q2. As far as my understanding goes, variables which are given a specific value by compiler are stored in data segment, and unintialized global and static variables are stored in BSS (Block started by symbol). In this case, MyClass::counter being static is initialized to zero by the compiler and so it is stored at BSS and MyClass::number which is initialized to 100 is stored in the data segment. Am I correct in making the conclusion?
Q3. Consider following piece of codes:
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);
}
I hope I have made my questions clear to all
EDIT:
Please refer this article for some understanding on BSS
EDIT1: Changed the class name from MyInstance to MyClass as it was a poor name. Sincere Apologies
EDIT2: Changed the class member variable number from non-static to static
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
据我所知,这有点简化,但大部分是准确的。
在Java中,所有对象都在堆上分配(包括所有成员变量)。大多数其他内容(参数)都是引用,引用本身与本机类型(整数、长整型等)一起存储在堆栈中,但字符串除外,字符串更像是对象而不是本机类型。
在 C++ 中,如果您要使用“new”关键字分配所有对象,那么情况与 java 几乎相同,但在 C++ 中存在一种独特的情况,因为您可以在堆栈上分配对象(您并不总是必须使用“新”)。
另请注意,Java 的堆性能比 C 的堆性能更接近 C 的堆栈性能,垃圾收集器做了一些非常聪明的事情。它仍然不如堆栈好,但比堆好得多。这是必要的,因为 Java 无法在堆栈上分配对象。
This is somewhat simplified but mostly accurate to the best of my knowledge.
In Java, all objects are allocated on the heap (including all your member variables). Most other stuff (parameters) are references, and the references themselves are stored on the stack along with native types (ints, longs, etc) except string which is more of an object than a native type.
In C++, if you were to allocate all objects with the "new" keyword it would be pretty much the same situation as java, but there is one unique case in C++ because you can allocate objects on the stack instead (you don't always have to use "new").
Also note that Java's heap performance is closer to C's stack performance than C's heap performance, the garbage collector does some pretty smart stuff. It's still not quite as good as stack, but much better than a heap. This is necessary since Java can't allocate objects on the stack.
Q1
Java也在堆栈上存储变量,但类实例在堆上分配。在 C++ 中,您可以自由地在堆栈或堆上分配类实例。通过使用 new 关键字,您可以在堆上分配实例。
数据段不是堆的一部分,而是在进程启动时分配的。堆用于动态内存分配,而数据段是静态的并且内容在编译时已知。
BSS段只是一种优化,其中属于该数据段的所有未初始化或初始化为零的数据(例如字符串、常数等)都被移动到BSS段。数据段必须嵌入到可执行文件中,并且通过将“所有零”移动到末尾,可以将它们从可执行文件中删除。当加载可执行文件时,BSS 段被分配并初始化为零,并且编译器仍然能够知道 BSS 段内的各种缓冲区、变量等的地址。
Q2
MyClass::number
存储在分配MyClass
类的实例的位置。它可以位于堆上或堆栈上。请注意在第三季度中,a
如何指向在堆上分配的MyClass
实例,而localObj
是在堆栈上分配的。因此,a->number
位于堆上,而localObj.number
位于堆栈上。由于
MyClass::number
是一个实例变量,您不能像这样分配它:但是,您可以分配
MyClass::counter
因为它是静态的(除了它是私有的) :Q3
当您调用
doHello
时,变量localObj
(在main
中)通过引用传递。doHello
中的变量localObj
引用堆栈上的该变量。如果您更改它,更改将存储在分配main
中的localObj
的堆栈中。当您调用
doHelloAgain
时,变量localObj
(在main
中)被复制到堆栈上。在doHelloAgain
内部,变量localObj
在堆栈上分配,并且仅在调用期间存在。Q1
Java also stores variables on the stack but class instances are allocated on the heap. In C++ you are free to allocate your class instances either on the stack or on the heap. By using the
new
keyword you allocate the instance on the heap.The data segment is not part of the heap, but is allocated when the process starts. The heap is used for dynamic memory allocations while the data segment is static and the contents is known at compile time.
The BSS segment is simply an optimization where all the data belongning to the data segment (e.g. string, constant numbers etc.) that are not initialized or initialized to zero are moved to the BSS segment. The data segment has to be embedded into the executable and by moveing "all the zeros" to the end they can be removed from the executable. When the executable is loaded the BSS segment is allocated and initialized to zero, and the compiler is still able to know the addresses of the various buffers, variables etc. inside the BSS segment.
Q2
MyClass::number
is stored where the instance ofMyClass
class is allocated. It could be either on the heap or on the stack. Notice in Q3 howa
points to an instance ofMyClass
allocated on the heap whilelocalObj
is allocated on the stack. Thusa->number
is located on the heap whilelocalObj.number
is located on the stack.As
MyClass::number
is an instance variable you cannot assign it like this:However, you can assign
MyClass::counter
as it is static (except that it is private):Q3
When you call
doHello
the variablelocalObj
(inmain
) is passed by reference. The variablelocalObj
indoHello
refers back to that variable on the stack. If you change it the changes will be stored on the stack wherelocalObj
inmain
is allocated.When you call
doHelloAgain
the variablelocalObj
(inmain
) is copied onto the stack. InsidedoHelloAgain
the variablelocalObj
is allocated on the stack and only exists for the duration of the call.在 C++ 中,对象可以在堆栈上分配...例如,Q3 主例程中的 localObj。
我感觉到类与实例之间存在一些混淆。 “MyInstance”作为变量名比类名更有意义。在您的 Q1 示例中,“number”存在于 MyInstance 类型的每个对象中。 “计数器”由所有实例共享。 “MyInstance::counter = 100”是有效的分配,但“MyInstance::number = 100”不是,因为您尚未指定
应该将其“number”成员分配给哪个对象。
In C++, objects may be allocated on the stack...for example, localObj in your Q3 main routine.
I sense some confusion about classes versus instances. "MyInstance" makes more sense as a variable name than a class name. In your Q1 example, "number" is present in each object of type MyInstance. "counter" is shared by all instances. "MyInstance::counter = 100" is a valid assignment, but "MyInstance::number = 100" is not, because you haven't specified
which object should have its "number" member assigned to.
不,数据部分与堆是分开的。基本上,数据部分是在加载时分配的,之后所有内容都有一个固定的位置。此外,对象可以在堆栈上分配。
对象位于堆上的唯一时间是使用
new
关键字,或者使用malloc
系列函数中的某些内容。是的,您对BSS部分的理解是正确的。但是,由于
number
不是静态的,因此代码:不合法,因此需要将其设置为静态或在构造函数中正确初始化。如果在构造函数中初始化它,则无论分配拥有的对象,它都将存在。如果将其设为静态,它将最终出现在数据部分......如果有的话。通常,
static const int
变量可以直接内联到所使用的代码中,这样根本不需要全局变量。void doHello(MyInstance &localObj){
localObj 是对传递的对象的引用。据你所知,没有存储,它指的是传递的变量在哪里。实际上,在底层,可以在堆栈上传递一个指针来促进这一点。但如果可以的话,编译器也可以轻松地对其进行优化。
void doHelloAgain(MyInstance localObj){
传递参数的副本被放置在堆栈上。
localObj 在堆栈上。
No, the data section is separate from the heap. Basically, the data section is allocated at load time, everything there has a fixed location after that. In addition, objects can be allocated on the stack.
The only time objects are on the heap is if you use the
new
keyword, or if you use something from themalloc
family of functions.Yes, your understanding of the BSS section is correct. However, since
number
isn't static the code:isn't legal, it needs to be either made static or initialized in the constructor properly. If you initialize it in the constructor, it will exist wherever the owning object is allocated. If you make it static, it will end up in the data section... if anywhere. Often
static const int
variables can be inlined directly into the code used such that a global variable isn't needed at all.void doHello(MyInstance &localObj){
localObj is a reference to the passed object. As far as you know, there is no storage, it refers to wherever the variable being passed is. In reality, under the hood, a pointer may be passed on the stack to facilitate this. But The compiler may just as easily optimize that out if it can.
void doHelloAgain(MyInstance localObj){
a copy of the passed parameter is placed on the stack.
localObj is on the stack.
此处列出了 C++ 中的所有内存区域
All memory areas in C++ are listed here