我想知道在 C++ 中什么时候应该在堆栈上分配一个类?我有很强的 Java 背景,在 Java 中,所有类都使用 new
关键字分配在堆上。在 C++ 中,我可以在堆栈和堆分配之间进行选择,但现在引入了智能指针,分配所有不转移所有权的内容更有意义 std::unique_ptr
。
我真的想不出有什么情况需要或更好地使用堆栈分配。也许是为了对嵌入式系统进行某种优化?
最佳答案
每当函数作用域或控制 block 的作用域(例如 for
)时,使用自动(堆栈)分配, while
, if
等在函数内部 - 非常适合对象所需的生命周期。这样,如果对象拥有/控制任何资源,例如动态分配的内存、文件句柄等——它们将在析构函数调用期间被释放,因为该范围已离开。 (当垃圾收集器结束时,不会在某个不可预测的后期时间)。
只使用new
如果有明确的需求,例如:
需要对象的生命周期比函数范围长,
将所有权移交给其他代码
拥有一个指向基类的指针容器,然后您可以对其进行多态处理(即使用虚拟分派(dispatch)派生类函数实现),或者
特别大的分配会占用大量堆栈(您的操作系统/进程将“协商”一个限制,通常在 1-8+ 兆字节范围内)
- 如果这是您使用动态分配的唯一原因,并且您确实希望将对象的生命周期绑定(bind)到函数中的范围,则应使用本地
std::unique_ptr<>
管理动态内存,并确保无论您如何离开范围,它都会被释放:byreturn
,throw
,break
等等。(您也可以在std::unique_ptr<>
/class
中使用struct
数据成员来管理对象拥有的任何内存。)
- 如果这是您使用动态分配的唯一原因,并且您确实希望将对象的生命周期绑定(bind)到函数中的范围,则应使用本地
Mathieu Van Nevel 在下面评论了 C++11 的移动语义——相关的是,如果你在堆栈上有一个小的管理对象来控制大量动态分配的(堆)内存,移动语义会提供额外的保证和良好的- 管理对象何时将其资源移交给其他代码(通常是调用者,但可能是其他容器/对象寄存器)拥有的另一个管理对象的粒度控制。这种移交可以避免堆上的数据被复制/复制,即使是暂时的。此外,elision 和 return-value-optimisation 通常允许名义上的自动/堆栈托管变量直接在最终被分配/返回的某些内存中构造,而不是稍后复制到那里。
关于C++ 堆栈与堆分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36646493/