可能重复:
Does this type of memory get allocated on the heap or the stack?
我有一些与记忆相关的问题,我希望你们能够回答。考虑一下这段代码, Foo 表示一个包含大量方法和大量原始数据成员的大类:
class Foo {
public:
Foo() : // Initialize all data members ...
{ }
// Lots of methods ...
~Foo() { /*Nothing needed here ... correct?*/ }
private:
int a;
int b;
char c;
double d;
// Lots of other primitive data members (no pointers) ...
};
class Bar {
public:
void func() {
foo = new Foo();
}
// Assuming Bar::func() is always called before deletion ...
~Bar() { delete foo; }
private:
Foo* foo;
};
int main() {
Bar bar;
bar.func();
Bar* barptr;
barptr->func();
return 0;
}
我的问题是,当我致电bar.func()
时,堆栈内存或堆上分配的Foo
的所有数据成员记忆(我知道foo
会在堆上......我想!)?我打电话给barptr->func()
时呢?例如,堆栈上还是堆上的Foo::a
?
此外,我是否需要明确删除Foo::~Foo()
中的任何内容? Foo 只有原始的本地数据成员,并且所有功能都不使用new
或malloc()
。
如果我完全不知道我在说什么,如果有人能解释存储这些数据的位置,我会很感激。
答案 0 :(得分:4)
分配有new
的所有内容都在堆上,包括其所有成员。第foo = new Foo();
行在堆上创建了一个Foo(包括 all 其成员)
只有命名对象在堆栈中。在您的情况下bar
(a Bar
)和barptr
(指向Bar
的指针)。
Foo
析构函数不需要做任何事情,这实际上很常见,如果你正确使用RAII,就像C ++一样。
在main
函数中,bar
是堆栈上的一个Bar
区域,它在堆上分配Foo
。如果barptr;
实际上已初始化,barptr
将是堆栈上的某个区域,该区域是指向某处Bar
的指针(可能不是堆栈)。但是,在每种情况下,都会在堆上分配Bar
个foo
成员,因为这是Bar
构造函数告诉它的内容。
在main
函数中,bar
是堆栈中的一个区域(指向(大型基元集合)的指针),它在堆上分配(大型基元集合) 。
如果实际初始化了barptr;
,那么barptr
将是堆栈上的一个区域,该区域是某个指针(指向(大型基元集合)的指针)(可能不是堆栈)。但是,在每种情况下,(大型基元集合)都将在堆上分配,因为这就是构造函数告诉它要做的事情。
因为我知道有人会提到它,所以堆/堆栈的区别在于编译器的奇思妙想,并且没有以任何方式标准化。完全允许“欺骗”并将其放在其他地方(如果感觉像这样)。例如,全局对象经常既不在堆栈上也不在堆中,而是在另一个地方。此外,尽管频繁(明显)使用内存管理,但C#和java仍然如此之快。编译器经常“欺骗”并将“动态范围”对象放在堆栈上。
答案 1 :(得分:1)
当你调用new Foo()时,你正在堆上创建一个新的Foo对象。
Foo中的所有原始数据成员都存储在Foo对象中。因此,它们也在堆上 - 在Foo对象内部。
您的Foo析构函数不需要显式处理原始数据成员。也不需要明确处理阶级类型的成员;在Foo的析构函数之后会自动调用它们的析构函数。
具有指向动态分配内容的裸指针的类通常需要在析构函数中使用显式语句来处理该内容。您可以使用std::auto_ptr
或boost::shared_ptr.