在内存中组织一个C ++程序
这个问题在这里已经有了答案:
我们一行一行地去看看。
int main() {
一条新的功能从这条线开始,并伴随着一个新的范围。
MyClass myClass(100), *p;
这里发生两件事。 一个,变量myClass
在函数的作用域内声明,这使得它成为一个局部变量,因此它被分配到栈中。 编译器将发出在堆栈上保留足够空间的机器指令(通常是通过颠倒sp
堆栈指针寄存器),然后执行对类构造函数的调用。 传递给构造函数的this
指针是堆栈分配的基础。
第二个变量p
只是一个本地指针,编译器(取决于优化)可能会将此值存储在本地堆栈或寄存器中。
cout << myClass.get_nmbr() << endl;
调用本地myClass
实例的get_nmbr()
方法。 同样, this
指针指向本地堆栈帧分配。 该函数找到实例变量i
的值并将其返回给调用者。 请注意,因为对象被分配在堆栈帧上,所以i
位于堆栈帧。
p = &myClass;
将myClass
实例的地址存储在变量p
。 这是一个堆栈地址。
cout << p;
return 0;
}
打印出局部变量p
并返回。
你所有的代码只关心堆栈分配。 这样做的结果是,当函数的作用域在执行时被关闭/关闭(例如函数返回)时,对象将被自动“析构”并释放其内存。 如果你从这个函数返回的指针类似于p
,那么你正在看一个悬挂的指针,即指向一个被释放和破坏的对象的指针。 (根据语言标准,通过这样一个悬挂指针进行内存访问的行为是“未定义的”。)
如果你想在堆上分配一个对象,并因此将它的生命周期扩展到声明范围之外,那么你在C ++中使用new操作符。 在引擎盖下, new
调用malloc然后调用一个合适的构造函数。
你可以将上面的例子扩展到如下所示的内容:
{
MyClass stackObj(100); // Allocate an instance of MyClass on the function's stack frame
MyClass *heapObj = new MyClass(100); // Allocate an instance of MyClass from the process heap.
printf("stack = %p heap = %pn", stackObj, heapObj);
// Scope closes, thus call the stackObj destructor, but no need to free stackObj memory as this is done automatically when the containing function returns.
delete heapObj; // Call heapObj destructor and free the heap allocation.
}
注意:你可能想看看新的位置,也许在这种情况下自动指针和共享指针。
首先要做的事情。 在C ++中,你不应该使用malloc
。
在这个程序中,所有使用的内存都在堆栈中。 让我们一次看一个:
MyClass myClass(100);
myClass
是堆栈上的一个自动变量,其大小等于sizeof(MyClass);
。 这包括成员i
。
MyClass *p;
p
是堆栈中的一个自动变量,指向MyClass
一个实例。 由于未初始化,因此可以指向任何地方,不应使用。 它的大小等于sizeof(MyClass*);
它可能(但不一定)在myClass
之后立即放置在堆栈上。
cout << myClass.get_nmbr() << endl;
MyClass::get_nmbr()
返回myClass
实例的成员i
的副本。 这个副本可能会被优化掉,因此不会占用任何额外的内存。 如果确实如此,它将在堆栈中。 ostream& operator<< (int val);
是具体实现。
p = &myClass;
这里p
指向一个有效的MyClass
实例,但由于实例已经存在,所以内存布局没有任何变化。
cout << p;
输出myClass
的地址。 operator<<
的行为再次是实现特定的。
该程序(种类)可视化自动变量的布局。
你在堆栈上创建myClass对象和指针p(声明为MyClass *)。 所以。 在myClass对象中,我也在stack上创建数据成员,作为myClass对象的一部分。 指针p存储在堆栈中,但不是为p分配的,而是将p分配给已存储在堆栈中的myClass对象的地址。 所以,在这里没有堆分配,至少从你发布的程序段。
链接地址: http://www.djcxy.com/p/2261.html