【问题标题】:How do I prevent deletion of a pointer without using const?如何在不使用 const 的情况下防止删除指针?
【发布时间】:2010-11-14 22:27:28
【问题描述】:

我有一个包含对象指针向量的类。我在该类中有一个 GetObject(..) 函数,它查看向量,找到所需的对象,并返回一个指向它的指针。但是,如果该类的用户对该返回的指针执行 delete(),我的程序将崩溃,因为该向量仍然具有指向该对象的指针,该指针现在无效。因此,在我的 GetObject() 类中,我可以返回一个 const 指针,但这并不能解决问题,因为您仍然可以删除该对象。该对象是可变的,因此我无法返回指向 const 对象的指针。我想我可以通过返回对对象的引用来防止删除,但是如果出现错误,我的函数会返回 NULL。我想我可以通过参数传回对象引用,然后像这样返回和错误号

//-1 on object on found. 0 for success. Object is passed back in 
// the function parameter result.
int MyObject::GetObject(int object_id, Item& result)

这是针对这种情况的最佳解决方案吗?

【问题讨论】:

    标签: c++ design-patterns


    【解决方案1】:

    解决此问题的最佳方法是使用共享所有权智能指针,例如 shared_ptr,您可以在 Boost、C++ TR1 和 C++0x 中找到它。

    智能指针是为您管理动态分配对象的生命周期的容器。当您使用完对象后,它负责deleteing 对象。

    使用共享所有权智能指针,您可以拥有多个共享动态分配对象的所有权的智能指针。保留一个引用计数,跟踪有多少智能指针拥有该对象的所有权,当最后一个拥有的智能指针被销毁时,动态分配的对象为deleted。

    在 C++ 中手动管理资源非常困难,编写看起来正确且大部分时间都可以正常工作但仍然不正确的代码非常容易。通过使用智能指针和其他拥有资源的容器(如标准库容器),您不再需要手动管理资源。当您的所有资源管理都是自动的时,编写正确的代码会容易得多。

    C++ 中的自动资源管理是使用称为Resource Acquisition is Initialization (RAII) 的设计模式完成的,这可以说是您作为 C++ 程序员应该熟悉的最重要的设计模式。

    【讨论】:

    • +1:这是一个好的解决方案的最相关原因是,使用智能指针,他们不能再直接在对象上调用 delete,而没有很多明显错误/明显邪恶的 hack。正如詹姆斯已经描述的那样,还有其他好处,但这是最适用于这个问题的一个。
    【解决方案2】:

    您代码中的任何人也可以尝试取消对 NULL 的引用。你也要阻止他们这样做吗?如果您的容器拥有该对象,并且您清楚地说明了这一点(返回原始指针通常很清楚或在文档中提到),那么任何删除它的人,结果都是他们自己的错。您可以保证防止删除对象的唯一方法是防止用户获得本机引用或指针 - 在这种情况下,他们无法访问该对象。

    【讨论】:

      【解决方案3】:

      谁是你班的客户?如果他们不是你的死敌,你可以很好地要求他们不要删除该对象。否则,“他们”总会有办法把你搞砸。

      好的,一种可能的解决方案是将析构函数设为私有。这将阻止每个人删除该对象。但随后对象必须以某种方式删除自己(delete this),可能是通过一些名为DeletObjectButDontBlameMeIfAppCrashes 的函数。如果所有者是其他类,那么您可以将析构函数设置为受保护,并将所有者类设置为此类的朋友。

      【讨论】:

        【解决方案4】:

        您应该返回对该对象的引用。找不到对象的情况有两种处理方式。

        首先,您可以使用Null Object Pattern 为这种情况实现一个特殊值。不过,这对您的情况可能没有意义。

        另一种方法是将其拆分为两种方法,一种用于检查是否存在适当的元素,另一种用于检索它。

        许多 STL 容器或算法都实现了这两者,或者通过返回一个过去的迭代器,或者通过将 empty() returns false 作为调用 frontback 等方法的先决条件。

        【讨论】:

        • 另一种方法是如果没有找到对象则抛出异常,我想。您的调用者是否会为此感谢您,这取决于您返回 null 时他们当前正在做什么。
        【解决方案5】:

        如果您可以使用 boost 库,则可以使用 smart pointers 来确保指针保持有效。本质上,对智能指针的每个引用都会将其“使用计数”增加 1。当在引用上调用 reset 函数时,引用消失并且使用计数器递减。只要某个对象仍然持有智能指针,引用就会有效。请注意,其他类将能够更改其指向的内容,但不能删除它。

        (我的描述主要针对智能指针,不同类型的指针略有不同,但总体思路是一样的)。

        【讨论】:

          猜你喜欢
          • 2016-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多