什么时候在C ++中使用new?

时间:2010-07-10 05:17:55

标签: c++ oop

何时使用“new”制作课程实例的好政策是什么?我已经习惯了一段时间编程C ++,但我仍然不确定什么时候才能做到这一点:

MyClass thing(param1, param2);

对此:

MyClass* thing;
thing = new MyClass(param1, param2);

有什么建议吗?

6 个答案:

答案 0 :(得分:22)

设计方面,尽可能使用自动(堆栈)分配。只要您需要将对象的生命周期延长到某个范围之外,就可以动态分配它。

即便如此,也绝不动态分配 raw 。始终将它们包装到某种包装器中,该包装器实现了Scope-Bound Resource Management(SBRM,首先以哑/尴尬的名称资源获取初始化或RAII而闻名)。也就是说,动态分配应该保存在将要清理的自动对象中自动启动!

一个很好的例子就是std::vector:你不能泄漏vector内部的内存,因为它的析构函数是在内存应该被释放的每个场景中运行的,它会释放它为了你。 auto_ptr是标准库中第一个也是唯一可用的智能指针,但它非常糟糕。更好的方法是使用shared_ptr,或Boost和/或TR1和/或C ++ 0x中提供的许多其他流行的智能指针。

性能方面,在堆栈上分配的对象可以快速完成非常(每个函数调用增加堆栈大小,因此所有必需的内存都已预先分配给了简单地移动指针。)相反,动态分配通常需要更多的时间。使用自定义分配方案可以获得快速的动态分配,但即使是最好的也会比堆栈分配慢。

有时,您可能会发现花费太多时间复制周围的对象。在这种情况下,动态分配它并仅仅移动指针可能是值得的。但是,请注意我说“找到”。这种变化是你通过剖析和测量找到的东西,从不猜测。

所以:尽可能自动分配,需要时动态分配。

答案 1 :(得分:5)

第一种方法在堆栈上创建一个本地实例,当调用函数退出时,该实例就会消失。第二个创建一个保留在堆上的实例,直到(以及如果)再次显式释放它。选择取决于您对对象的控制和生命周期。

答案 2 :(得分:2)

经验法则是:如果没有new,则不要使用new

答案 3 :(得分:2)

一般情况下:如果您打算删除同一范围内的对象,则无需使用new。如果对象非常大,您可能需要使用new 如果您想了解详细信息,可能需要查看堆和堆栈内存之间的区别。

答案 4 :(得分:1)

首先,问问自己这个问题,当另一个函数想要复制对象时,它是否有意义?

如果复制对象是有意义的,最好的办法是在堆栈上创建所有内容或作为成员变量,然后在需要时传递副本。

如果复制对象没有意义,则需要使用new表单,以便可以安全地将指针传递给对象。您必须使用指针(或引用),因为如上所述,复制对象没有意义。

我知道有两个例外:

如果您知道在当前函数完成后将不会使用该对象,则可以在堆栈上创建该对象以便将其删除。只是确保之后没有人抓住它的指针! (我很少发现情况如此,但它确实发生了)

如果对象在内部由另一个本身使用,而这个类本身不应该被复制,那么你可以将它作为成员变量放入。由于它所在的对象不会被复制,因此只能用于内部使用,这是安全的。

答案 5 :(得分:0)

 MyClass thing(param1, param2); //memory for thing is allocated on the process stack(static allocation)

 MyClass* thing;
 thing = new MyClass(param1, param2); //memory is allocated dynamically on the heap(free store) for thing

不同之处在于:

 int main()
 { 
   {
    MyClass thing(param1, param2); //thing is local to the scope
   } //destructor called for thing
   //cannot access thing (thing doesn't exist)
 } 

 int main()
 {
   {
     MyClass* thing;
     thing = new MyClass(param1, param2);
   }
  //the object pointed to by thing still exists
   //Memory leak
 }  

对于大型对象,您必须动态分配内存(使用new),因为进程堆栈的大小有限。