2010-10-21 63 views
2

Circle是一个类,公共方法为GetDiameter()。 下面两组代码有什么区别?用C++在堆或栈上创建变量

的Qn1:是否方法1(因此不需要空闲内存)分配用于c存储器,而方法2(无需手动释放内存)分配用于c存储器?

Qn2:什么时候应该使用方法1或方法2?

方法1:

void Init() 
{ 
Circle c; 
c.GetDiameter(); 

return; 
} 

方法2:

void Init() 
{ 
Circle *c = new Circle(); 
c->GetDiameter(); 

return; 
} 
+0

你是怎么知道的? :) – ruslik 2010-10-21 12:56:16

+0

我怀疑它。只是想确认一下。 – seveleven 2010-10-21 12:59:04

回答

10

作为良好编码实践的一般规则,应尽可能使用方法1。 仅当您需要在不同位置存储和/或共享指针时才应使用方法2。所有在方法或类中仅在本地使用的对象应放入堆栈中。

+1

小调:异常是巨大的对象,sizeof(SomeClass)与整个堆栈大小相当。 – valdo 2010-10-21 14:37:01

2

是,方法1个分配对堆栈,因此没有必要释放,其中作为堆方法2个分配其必须被释放。

  1. 使用堆栈,如果你不想要的功能
  2. 使用堆结束后的对象,如果你想保留的对象活着的功能的退出也后(前提是您保留分配的地址)
+1

啊,但'Circle :: operator new()'可能会被覆盖以使用'alloca()'来分配堆栈内存。但实例仍然需要被“删除”。我爱C++ :) – 2010-10-21 13:00:14

+0

@Frédéric:我不认为这实际上是允许的。在编译时,结果几乎肯定是未定义的,因为'operator new'被定义为对具有动态存储持续时间的对象执行分配。 'alloca()'不返回指向具有动态存储持续时间的内存的指针。然而,符合'operator new'的重载可能总是抛出'bad_alloc';虽然... – 2010-10-21 13:34:22

+0

你说的那些“允许”或“未定义”或“符合”的东西是什么?如果它编译,我们将发布它,pronto;) – 2010-10-21 13:52:20

6

使用方法2时:

  • 对象的寿命超过了功能的 或
  • 当调用一些函数,返回指针,即要创建来自物体的范围的抽象工厂或类似工厂。

后一种技术通常用于处理多态性,所以您得到的类型实际上可能不是指针的类型,而是从它派生的类。

无论何时您需要删除返回值,最好通过将其封装在智能指针或其他会自动销毁的对象中进行处理。

如果在函数结束时要做清理工作,理想情况下应该使用自动对象(如scoped_ptr或auto_ptr)来完成。这可以确保即使函数尽早终止,清理也会发生(例如抛出异常)。这种技术被称为RAII - 资源获取是初始化。

+1

+1,还注意到一个新的缩写SBRM(Scoped Bound Resources Management)是RAII的同义词,但名称更清晰。 – 2010-10-21 14:25:56

1

方法1:在堆栈上分配内存。方法2:在堆上分配的内存。 + 作为一般规则,如果您使用call'new',则必须调用'delete'来释放内存。

2

上堆与栈我见过的最好的讨论,一个是在这里:heap vs. stack(向下滚动到讨论中)

简短的摘要:

  • 栈:对象的生命周期是由编译器
  • 控制
  • 堆:对象的生存期由程序员
  • 0

    堆栈

      控制
    • 限定和固定大小
    • Stricked最后在入先出对象的生存期(通常限于封闭函数)

    • 尺寸通常仅由系统存储器的大小受限
    • 手动管理对象的使用寿命

    这意味着对于只有短寿命的理想小物体。对于大对象或具有比创建函数更长的生命周期的任何对象,都需要堆。手动对象的生命周期意味着如果你不小心的话,你可以开发内存泄漏。

    1

    你甚至还没有开始使用指针,方法2已经有内存泄漏。

    +0

    Yikes,这个^^^ – rossb83 2016-12-20 22:38:39