本地变量或指针

3
给定任何一个C++框架中的一个类,如何知道是否需要在栈上创建一个简单对象或者在堆上创建一个指向对象的指针?
假设有一个函数接受引用(&)变量作为参数形式。调用方可以传递一个本地变量或指针(*ptr)。被调用函数可能会拷贝传入对象的数据。
这个问题是我之前关于C++ Bada开发的问题的后续。

好问题!在C++中,我总的来说非常害怕堆栈对象。你需要记住堆栈的生命周期。但是我正在等待真正懂得回答的人。 :) - Prof. Falken
3
你可能做错了什么。C++非常喜欢堆栈对象,你不应该害怕它们。 - Konrad Rudolph
@Konrad Rudolph,我可能是,但我来这里是为了学习! :) - Prof. Falken
4个回答

6
一般来说,每个设计良好的C++库都允许二者。在大多数情况下,库不关心调用者分配内存的位置,因为调用者处理自己的内存。如果库有其他要求(例如接管指针的所有权),则会仔细记录这些要求。
此外,作为一般准则,应避免使用指针和堆内存。C++是以栈对象为中心设计的。除非有强制使用不同类型对象的原因,否则不要使用它们。在代码中应极少使用new,而且永远不应该使用delete - 也就是说,始终让智能指针处理你已分配的内存。

除了必须在智能指针内使用delete,对吧? :) - Prof. Falken
1
@Amigable 是的,但这不再是的责任。在你的代码中有delete是代码异味的一个非常明显的迹象,除非你恰好实现了一个智能指针(或垃圾回收)库。在所有其他情况下,它都是不合适的。 - Konrad Rudolph

1

创建对象的方式取决于您打算用它做什么。

如果您使用new语句创建对象,则会得到指向手动分配对象的指针。只要不使用delete手动释放,该对象将一直存在。

如果您在堆栈上创建一个简单对象,则只要当前堆栈被使用,即作用域未改变,该对象就会一直存在。

常见库(如STL)将允许这两种对象。

如果库有特殊要求,则必须在某个地方记录下来,并且主要解释是因为它想拥有该对象。


0

不存在所谓的“简单对象”。一个对象就是一个对象。

重要的是对象的生命周期:自动(作用域),动态(手动)或静态(永久)。

尽量使用具有自动生命周期的对象,除非你有一个真正很好的理由去使用其他类型。

如果你考虑一个对象如何依赖于另一个对象,你会发现,如果你只使用自动对象,那么你不会遇到悬空引用的问题(或者说“对局部变量的引用”),因为依赖对象的作用域比被引用对象更深。

你应该有一个非常有说服力的理由,说明为什么一个特定的对象必须具有手动生命周期。当然,这些情况确实会发生,但它们应该被抽象化和分解。例如,大多数标准库容器当然需要手动管理它们的元素,但所有这些都由容器处理,因此用户可以只使用自动生命周期的容器对象,一切都很好。最后,如果你决定真的必须手动管理对象的生命周期,那么使用单一职责资源管理类,如shared_ptrunique_ptr来传递该对象的句柄--处理程序类现在又变成了自动的,一旦它们超出作用域,它们就会为您释放托管对象。你得到了最好的两个世界:手动对象分配的好处和范围责任。

如果你按照这些思路有条不紊地工作,你会发现自己很少创建动态对象,而且如果你这样做了,只需要一行相关的代码(这使得你“局部化”);例如,auto p = std::make_shared<T>(a,b,c); 或者 std::unique_ptr<T> p(new T(a,b,c));。在所有源代码上进行简单的 grep 查找 new 就可以轻松审计是否负责处理了所有动态分配。


0

有很多事情需要考虑。当决定是否使用指针时,寿命、多态性、引用和性能都是需要考虑的因素。

正如其他人所说,堆栈空间具有作用域寿命。一旦变量超出范围,它就完成了。通过指针分配的内存将持续到调用delete为止,但请记住指针本身仍将超出范围!因此,请确保在某个地方保留引用!

至于多态性,使用堆栈空间会导致切片问题不可能发生。因此,如果您需要使用此技术,请坚持使用指针。

引用应该是显而易见的。您需要将相同的内存移动到程序中的各个位置吗?多个事物需要访问完全相同的内存,而不仅仅是副本吗?

最后,性能。使用堆内存会给您带来性能损失吗?指针较慢,因为需要额外的分配时间。它们还需要一些额外的内存来存储指针本身(实际上微不足道,但您可能也要考虑一下。这真的取决于您的应用程序)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接