我前段时间和朋友讨论过。他是一位经验丰富的C ++用户,我不是一位经验丰富的C ++用户。他告诉我,我应该努力使用堆变量,即:
A* obj = new A("A");
而不是:
A obj("A");
除了使用指针好又灵活的所有东西之外,他说把东西放在堆而不是堆栈中更好(堆栈的东西比堆小?)。这是真的吗?如果是这样的话?
编辑:我说我的朋友建议堆栈变量我写了一个错字。他在推荐堆变量。
Edit2:我知道有关生命的问题。让我们假设我已经适当地管理了这些变量的生命周期。 (即关注的唯一标准是堆与堆栈存储,没有终身问题)
答案 0 :(得分:12)
根据上下文,我们需要使用堆或堆栈。每个线程都获得一个堆栈,线程通过调用函数来执行指令。调用函数时,函数变量将被推送到堆栈。当函数返回堆栈回滚并回收内存时。现在线程局部堆栈有一个大小限制,它有所不同,可以在某种程度上进行调整。如果在堆栈上创建每个对象并且对象需要大内存,则考虑到此限制,则堆栈可能会耗尽,从而导致堆栈溢出错误。除此之外,如果要通过多个线程访问对象,那么将这样的对象存储在堆栈上是没有意义的。
因此,应将小变量,小对象和指针存储在堆栈中。将对象存储在堆或免费存储上的问题是,内存管理变得困难。内存泄漏的可能性很大,这很糟糕。此外,如果应用程序尝试访问已删除的对象,则可能会发生访问冲突,从而导致应用程序崩溃。
C ++ 11引入了智能指针(共享,唯一),使堆内存管理更容易。实际引用的对象在堆上,但是由智能指针封装,该指针始终在堆栈上。因此,当函数返回事件期间或异常期间堆栈回滚时,智能指针的析构函数会删除堆上的实际对象。在共享指针的情况下,保持引用计数,并且当引用计数为零时删除实际对象。 http://en.wikipedia.org/wiki/Smart_pointer
答案 1 :(得分:7)
堆栈应该优先于堆,因为堆栈分配的变量是自动变量:当程序退出上下文时,它们的销毁会自动完成。
实际上,在堆栈和堆上创建的对象的生命周期是不同的:
{}
的局部变量(未由new分配)在堆栈上 。从函数返回时,它们自动销毁。 (他们的析构函数被调用,他们的记忆被释放)。示例:
void myFun()
{
A onStack; // On the stack
A* onHeap = new A(); // On the heap
// Do things...
} // End of the function onStack is destroyed, but the &onHeap is still alive
在此示例中,onHeap
在函数结束时仍将分配其内存。这样,如果某个地方没有指向onHeap
的指针,您将无法删除它并释放内存。这是一个内存泄漏,因为在程序结束之前内存将会丢失。
但是如果要在onStack
上返回一个指针,因为退出函数时onStack
被销毁,使用指针可能会导致未定义的行为。使用onHeap
仍然完全有效。
为了更好地了解堆栈变量的工作原理,您应该搜索有关调用堆栈的信息,例如this article on Wikipedia。它解释了如何堆叠变量以在函数中使用。
答案 2 :(得分:4)
最好避免在C ++中尽可能多地使用 new
但是,有时候你无法避免它
例如:
希望变量存在于其范围之外。
所以它应该是真正的课程,但如果你有选择总是避免堆分配变量。
答案 3 :(得分:4)
关于堆栈分配与堆分配变量的使用,没有一般规则。根据您的目的,只有指南。
以下是一些优点和缺点:
堆分配:
优点:
缺点:
堆栈分配:
优点:
缺点:
我认为这抓住了一些利弊。我相信还有更多。
最终取决于您的应用需求。
答案 4 :(得分:1)
答案并不像有些人会让你相信那样明确。
通常,您应该更喜欢自动变量(在堆栈上),因为它更容易。但是有些情况需要动态分配(在堆上):
后者有点棘手。从理论上讲,自动变量可以无限分配,但计算机是有限的,更糟糕的是,大多数情况下堆栈的大小也是有限的(这是一个实现问题)。
就个人而言,我使用以下指南:
std::vector<T>
,在内部动态分配它们它对我很有帮助(显然这只是轶事证据)。
注意:您可以(并且可能应该)使用RAII将动态分配的对象的生命周期与堆栈变量的生命周期联系起来:智能指针或容器。
答案 5 :(得分:0)
C ++没有提到堆或堆栈。就语言而言,它们不存在/不是分开的东西。
至于实际答案 - 使用最有效的方法 - 你需要快速 - 你需要保证吗?对于堆上的所有内容,应用程序A可能会好得多,应用程序B可能会破坏操作系统内存,因此它会杀死机器 - 没有正确的答案: - (
答案 6 :(得分:0)
简单地说,除非你需要,否则不要管理你自己的记忆。 ;)
答案 7 :(得分:-4)
Stack =在编译期间分配的静态数据。 (不是动态的)
堆=运行时分配的动态数据。 (非常有活力)
尽管指针位于堆栈上......这些指针很漂亮,因为它们为动态,自发的数据创建打开了大门(取决于您对程序进行编码的方式)。
(但我只是一个野蛮人,所以为什么我说的很重要)