何时使用“new”制作课程实例的好政策是什么?我已经习惯了一段时间编程C ++,但我仍然不确定什么时候才能做到这一点:
MyClass thing(param1, param2);
对此:
MyClass* thing;
thing = new MyClass(param1, param2);
有什么建议吗?
答案 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),因为进程堆栈的大小有限。