要删除还是不删除(调用func)?

时间:2009-01-03 15:19:25

标签: c++

我记得有人说如果你通过lib创建一个类,你应该通过库来销毁它。那么,这是否意味着我不应该叫删除?我应该致电myclass.deleteMe()而不是?重载删除会解决问题吗?

5 个答案:

答案 0 :(得分:6)

  

我记得有人说如果你通过lib创建一个类,你应该通过lib来销毁它。

这意味着如果你在lib中调用一个函数为你创建一个对象,你应该阅读该函数的文档,它必须说明你如何再次释放该对象。通常,免费内容的函数被命名为类似于分配函数。例如,库pcre有两个名为pcre_mallocpcre_free的函数。

原因是,因为库以一种对你不透明的方式分配(这是你首先使用该函数的原因)。它可以从程序的数据部分获取内存,而您(错误地)假设它在使用delete时可能从堆中获取内存。

如果是该库编写者,则适用相同的规则。确保当你的一个函数返回一个动态分配的对象时,你会说出调用者如何处理它

  1. 对象是否封装成智能指针?然后智能指针将负责调用您指定的相应删除器
  2. 你是否返回原始指针?您应该避免这种情况,因为调用者必须跟踪指针,并且调用者必须将指针传递到接口中的函数 you 文档。这只是你对图书馆用户负担的另一个依赖程度,哪些智能指针可以优雅地合理化。
  3. 您是否按值返回一个对象,它本身包含一个已分配的资源?如果是这种情况,请重载该对象类的复制构造函数,复制赋值运算符和析构函数,然后通过正确复制或在其对象的所有其他实例之间共享资源来管理资源(请参阅this answer)。
  4. 除非您还重载了新运算符,否则您几乎不会为类重载删除运算符。重载delete运算符不是字面意思:它意味着你只是重载对象的相关内存的 deallocation 。只有在您拥有自己的内存池或想要记录对象的每个内存分配/释放时才有意义。

答案 1 :(得分:2)

您的应用程序删除在lib中创建的内容的问题是lib可能使用不同的堆/内存管理器。

解决方案包括:

  • 确保使用与库相同的堆管理器构建应用程序。
  • 在类中实现(非内联)deleteMe方法,其实现可以是delete this;
  • 在类中定义自定义operator delete,在库中实现...如果有自定义运算符删除,那么当应用程序删除对象的istance时,它将被调用。

答案 2 :(得分:0)

此规则适用于设计的类。 经验法则(虽然并不总是使用)是,如果一个类创建一个对象,它应该删除它。

但如果你问其他人设计的某个图书馆,你不知道他是否遵守这条规则,你必须通过himselef / documentation / code检查它。

答案 3 :(得分:0)

您应该查阅库的文档,了解如何删除它创建的对象。除了其他人提到的内容之外,有时候图书馆会期望何时删除对象。例如,在wxWidgets中,你不应该自己删除小部件,因为wxWidgets会在他们的父小部件被销毁时尝试删除它们 - 如果你已经删除了它们,那么你有一个双重自由(未定义的行为)。通过查看类型无法确定这一点 - 即使库不返回智能指针,库也可以这种方式运行。此外,库可能依赖于以特定顺序发生的解除分配(例如,它可能总是在另一个类型之前释放所有类型的对象),并且删除事物本身会破坏订单。

答案 4 :(得分:0)

如果你的库提供了一个特定的方法来构造对象,就内存管理器等而言,你应该有没有的方法来摆脱那个对象,除非通过一种有意义的方式来处理对象的形式与它的构造/分配方式类似。

换句话说,如果您的对象倾向于以某种方式分配,请确保所有摆脱它们的方法都遵循“特定方式”。