我有点困惑何时/如何从 C++ 中的堆中删除对象。
什么时候:
如果您正在执行一个相对较短的程序,计算一些东西然后将标准输出传递到控制台,是否值得在控制台输出结果后立即销毁所有对象,或者程序会在退出时自动销毁?对于大型程序,我认为当您不再需要任何对象时尝试解决肯定是更好的做法?
如何:
如果我有一个包含指向 MyClass 对象的指针的向量,一旦我完成了向量(和 MyClass 对象),我该如何编写一个析构函数来破坏向量指向的所有 MyClass 对象?(显然我也需要销毁向量)。
我有点困惑何时/如何从 C++ 中的堆中删除对象。
什么时候:
如果您正在执行一个相对较短的程序,计算一些东西然后将标准输出传递到控制台,是否值得在控制台输出结果后立即销毁所有对象,或者程序会在退出时自动销毁?对于大型程序,我认为当您不再需要任何对象时尝试解决肯定是更好的做法?
如何:
如果我有一个包含指向 MyClass 对象的指针的向量,一旦我完成了向量(和 MyClass 对象),我该如何编写一个析构函数来破坏向量指向的所有 MyClass 对象?(显然我也需要销毁向量)。
这是一个非常简单的契约——所有编程中最简单的契约之一:如果你分配一个资源,你就向 API 承诺你会适当地释放它。
不这样做会产生不良后果。从浪费堆空间到咀嚼你内脏的鼻恶魔。
事实是,根本没有理由不释放您请求的资源。不这样做是草率的,我认为这表明代码质量通常很差(因为它是!)。
此外,C++ 使不必做出这个决定变得非常容易:只要不产生垃圾,就不需要清理。不要分配 freestore 内存,或者如果你绝对必须使用智能指针或特殊分配器来管理它。
如果您正确使用 C++,就没有令人信服的技术理由来草率使用资源,并且有足够的动力去关注。
至于“如何”,我首先质疑存储指针的决定:原始 C++ 指针不应该拥有内存。如果您确实需要 freestore 内存,请使用智能指针,或者(最好)使用自动对象:因为它们位于向量中,这已经为您提供了所有权和存储位置,并且向量类会自动处理该内存。
如果您需要多态对象,不幸的是您需要存储指针。在这种情况下,有几种可能性,但最简单的可能是使用智能指针。
如果您在使用完对象后没有销毁它们,那么您将面临内存/资源泄漏。如果你失去了对物体的追踪,那么你就有了泄漏。
这是长时间运行的程序中的一个问题,因为您可能会耗尽内存或资源。如果没有正确跟踪对象,这在任何程序中都是一个不好的迹象。你创造了这个物体,为什么你不能也摧毁它?
大多数(每个?)操作系统都会在进程退出时从进程中回收分配的内存,因此您不需要自己整理。在某些情况下,避免这种毫无意义的整理可能意味着您的用户在您的流程完成时不会等待太久。
如果您的程序的行为是这样的,它会使您的代码无法重用。如果你想将它打包到一个库中,你将不得不处理这个问题,因为你无法提前知道你的库将如何被使用。
至于您的指针向量:迭代向量并在每个指针上调用 delete 。然后销毁向量。
如何编写一个可以销毁向量指向的所有 MyClass 对象的析构函数?
非常好的问题!具有这种析构函数的类称为智能指针,它们由 Boost、TR1 和 C++11 标准库等库提供,其中至少一个可能随您的平台提供。
你几乎不应该new T
直接使用。用于unique_ptr<T>
直接所有权(当且仅当向量仍然存在时,对象仍然存在)或shared_ptr<T>
共享所有权。这些模板存在于 namespace boost::
、std::tr1::
或std::
取决于您如何获取它们。在任何情况下,接口都大致相同。
当然,如果可以避免的话,你根本不应该使用任何类型的指针。vector<T>
比vector< unique_ptr< T > >
任何一天都好。
至于退出前是否释放资源,当然应该。良好的 C++ 实践使得忽视释放资源比正确做事更难,所以这并不是我们真正担心的事情。
对于短期运行的程序,可以不删除对象。没有不良后果。
但是设计良好的应用程序代码是可重用的,而可重用的代码基本上是库代码。库代码应该删除它分配的对象,因为它可能在长时间运行的程序中使用。
所以换句话说,对于一个扔掉的小程序,不用担心。但是对于严肃的代码,删除对象而不是泄漏它们。