【问题标题】:To delete or to not delete (call func)?删除还是不删除(调用函数)?
【发布时间】:2014-08-10 17:42:27
【问题描述】:

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

【问题讨论】:

    标签: c++


    【解决方案1】:

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

    这意味着如果您调用库中的函数为您创建对象,您应该阅读该函数的文档,其中必须说明您如何再次释放该对象。通常,免费功能的名称类似于分配功能。例如,库pcre 有两个函数,分别称为pcre_malloc 和pcre_free。

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

    如果你是那个库作者,同样的规则适用。确保当您的某个函数返回一个动态分配的对象时,您说明调用者必须如何处理它

    1. 对象是否封装在智能指针中?然后智能指针将负责调用您指定的适当的 deleter。
    2. 是否返回原始指针?您应该避免这种情况,因为调用者必须跟踪指针,并且调用者必须将指针传递到接口中的函数 you 文档中。这只是您对库用户负担的另一层依赖,智能指针可以优雅地合理化。
    3. 您是否按值返回一个对象,该对象本身包装分配的资源?如果是这种情况,请重载该对象类的复制构造函数、复制赋值运算符和析构函数,然后通过正确复制或在其对象的所有其他实例之间共享资源来管理资源(参见this answer)。李>

    您几乎不应该为您的类重载 delete 运算符除非您还重载了 new 运算符。重载删除操作符不是字面意思:这意味着您只是重载对象关联内存的deallocation。仅当您拥有自己的内存池或想要记录对象的每个内存分配/释放时才有意义。

    【讨论】:

    • 我正在写这个库。我主要想知道重载删除运算符是否是最好的方法,或者虚拟类中的 deleteMe() 之类的东西。
    【解决方案2】:

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

    解决方案包括:

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

    【讨论】:

    • 我正在学习第三种解决方案。我不知道如何确保 lib 和应用程序(都是我的)是使用兼容的堆设置构建的。第 3 个听起来更自然,因为 delete obj;本能地是某人所做的,而不是检查 deleteMe 或某种删除功能。
    • 您说,“我不知道如何确保 lib 和应用程序(都是我的)是使用兼容的堆设置构建的。” ...您使用什么编译器和操作系统,您的库是静态库还是动态库?​​
    【解决方案3】:

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

    但是如果你问的是别人设计的某个库,你无法知道他是否遵守这个规则,你必须通过他自己/文档/代码来检查。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        如果您的库在内存管理器等方面提供了构造对象的特定方法,那么您应该没有方法可以摆脱该对象,除非通过一种有意义的方式来处理对象的构造/分配方式类似。

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

        【讨论】:

          猜你喜欢
          • 2017-11-30
          • 1970-01-01
          • 2011-02-18
          • 2011-11-05
          • 2013-09-30
          • 2019-07-24
          • 2013-02-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多