代码之家  ›  专栏  ›  技术社区  ›  laura

确保指针未被删除

  •  3
  • laura  · 技术社区  · 16 年前

    我遇到了一些我不知道的事情,所以我想我在C++的图片中缺少了一些东西。

    较长的版本是:

    我有以下场景:一堆类(我可以稍微修改,但不能完全重构),其中大多数需要使用对象。此对象虽然是可变的,但由其他人管理,因此不能将其删除。

    其中一些类不需要这样的对象——它们重用来自其他类的代码,但通过提供给这些类的可用参数,可以保证即使提供了对象,也不会使用它。

    当前实现使用指向const对象的指针( const Obj * )。这反过来意味着所有对象的方法都必须是常量,并且大多数字段都是可变的。这是一个混乱的解决方案,因为字段声明了 mutable 可用于检查(与C++的条目完全相反) here )。它还只是部分解决了“此处不删除此项”的问题(编译器不抱怨,但 const

    如果我使用了对这个对象的引用,我会强制一些调用方创建一个“虚拟”对象,并将其提供给他们正在实例化的类。除了浪费资源之外,这也是一件混乱的事情。由于项目限制,我无法创建全局对象来代替“NULL”引用。

    我觉得引用是我所需要的工具,但我不能重构所涉及的类,使对象从未使用的实现中消失(这是可以做到的,但并不简单,也不会很快)。所以我想实现一些更简单的东西,如果有人试图滥用这个对象,它只会发出一个警报信号,但会使我的对象保持可变。

    我能想到的最佳解决方案是使用指向对象的常量指针( Obj * const )-这不会让编译器抱怨,但我有我的可变对象和一种报警信号-通过 常数 -也到位了。

    6 回复  |  直到 16 年前
        1
  •  6
  •   denisenkom    16 年前

        2
  •  6
  •   Doug T.    16 年前

    我以前见过这种场景是使用共享的\u ptr/弱\u ptr组合实现的。看见 here.

    boost::shared_ptr<T>
    

    你们班会得到一个好成绩

    boost::weak_ptr<T>
    

    要重新分配弱ptr,只需重新分配指针:

    void MyClass::Reassign(boost::weak_ptr<T> tPtr)
    {
        m_tPtr = tPtr;
    }
    

    要使用弱ptr,首先检查它是否仍然存在:

    void MyClass::Use()
    {
        boost::shared_ptr<T> m_temporarySharedPtr = m_tPtr.lock();
        if (m_temporarySharedPtr)
        {
            //...
        }
    }
    

    void MyClass::MakeNull()
    {
        m_tPtr.reset();
    }
    
        3
  •  1
  •   Mike Seymour    16 年前

    template <typename T> class Wrapper
    {
    public:
        Wrapper(T *p=0) : pointer(p) {}
    
        T       *operator->()       {return pointer;}
        T const *operator->() const {return pointer;}
        operator bool()       const {return pointer;}
    
    private:
        T *pointer;
    };
    

    在某些上下文中,您可以像使用指向模板类型的指针一样使用它,但不能对其调用delete。包装类型必须是 struct class 类型(即 -> 有道理)。然后,使用但不管理对象生存期的某个类看起来有点像:

    class User
    {
    public:
        void Assign(Object *o) {object = o;}
        void UseObject() {if (object) object->Use();}
    
    private:
        Wrapper<Object> object;
    };
    

    从技术上讲,您仍然可以获取原始指针,但执行此操作的代码看起来非常错误:

    delete wrapper.operator->();
    
        4
  •  0
  •   Patrick    16 年前

        5
  •  0
  •   xan    16 年前

    如果类愿意,可以尝试删除此对象,但它本身将保持原始对象不变。重载*操作符,您可以透明地使用它。

        6
  •  0
  •   timB33    16 年前

    像这样的东西?。。。

    Obj类是新类的聚合,您可以使用 Obj* cont pObj

    if ( pObj ){ pObj->foo(); }
    

    您的新类不负责清理/删除Obj类。