简单包装器 class 与智能指针

Simple wrapper class vs. smart pointer

出于教育目的,我今天早些时候实现了一个包装器 class,定义如下(摘自一本书):

#ifndef WRAPPER_H
#define WRAPPER_H

template<class T>
class Wrapper
{
public:
  Wrapper()
  { dataPtr = 0; }

  Wrapper(const T& inner)
  {
    dataPtr = inner.clone();
  }

  Wrapper(const Wrapper<T> &original)
  {
    if (original.dataPtr != 0)
      dataPtr = original.dataPtr->clone();
    else
      dataPtr = 0;
  }

  Wrapper &operator =(const Wrapper<T> &original)
  {
    if (this != &original)
    {
        if (dataPtr != 0)
          delete dataPtr;

        dataPtr = (original.dataPtr !=0) ? original.dataPtr->clone() : 0;
    }
    return *this;
  }

  ~Wrapper()
  {
    if (dataPtr != 0)
      delete dataPtr;
  }

  T &operator*()
  {
    return *dataPtr;
  }

  const T&operator*() const
  {
    return *dataPtr;
  }

  T *operator->()
  {
    return dataPtr;
  }

  const T * const operator->() const
  {
    return dataPtr;
  }
private:
  T *dataPtr;
};

#endif

主要思想是充当指针,额外的优势是负责内存管理、复制构造函数、析构函数和赋值运算符。它包装了具有克隆方法的 classes:它们 return 一个指向它们自身副本的指针(不是指向它们自己,指向使用 new Class(*this) 制作的新副本)。

在某些方面它看起来像一个 unique_ptr,因为被包装的对象只能通过这个包装器访问。但是,有一个区别,这就是我的问题所在。在这个包装器 class 中,有一个构造函数通过接受对它包装的 class 对象的引用来定义(上面代码中的第一个构造函数)。

这很方便。假设我们有 classes ABB 的构造函数引用了 Wrapper< A >。然后我可以用另一个对象 A:

构造一个对象 B
A object1;
B object2(A);

这是因为object2使用前面提到的Wrapper构造函数构造一个Wrapper< A >(然后传递给B的构造函数)。

是否可以使用 std::memory 中的任何智能指针来执行此操作?我在这里的主要目标是教育,但实际上我不想重新发明轮子。

是的,所有这些都是可能的..并供参考..因为一旦我也实现了类似的东西..(也用于教育目的)..我可以分享我为智能指针制作的代码,带有引用计数..意味着你可以创建任意数量的副本,当最后一个副本被销毁时,它将删除对象

#ifndef UberPointer
#define UberPointer UPointer

template <class UClass> class UPointer
{
private:
    struct UPointerRef
    {
        UClass* pObject;
        int _nCount;
        UPointerRef(UClass* pRef){_nCount=0;pObject = pRef;}
        ~UPointerRef(){if(pObject)delete pObject;}
        void AddRef(void){++_nCount;}
        void RemoveRef(void){if (--_nCount <= 0){delete this;}}
    };
    UPointerRef* _pRef;

public:
    UPointer()
    {
        _pRef = new UPointerRef(0x0);
        _pRef->AddRef();
    }
    UPointer(UClass* pPointer)
    {
        _pRef = new UPointerRef(pPointer);
        _pRef->AddRef();
    }
    UPointer(UPointer<UClass> &oPointer)
    {
        _pRef = oPointer._pRef;
        _pRef->AddRef();
    }
    ~UPointer(void)
    {
        _pRef->RemoveRef();
    }
    UClass* GetObject()
    {
        ASSERT(_pRef->pObject);
        return _pRef->pObject;
    }
    operator UClass*(void)
    {
        ASSERT(_pRef->pObject);
        return _pRef->pObject;
    }
    UClass& operator*(void)
    {
        ASSERT(_pRef->pObject);
        return *(_pRef->pObject);
    }
    UClass* operator->(void)
    {
        ASSERT(_pRef->pObject);
        return (_pRef->pObject);
    }
    UPointer& operator=(UPointer<UClass> &oPointer)
    {
        _pRef->RemoveRef();
        _pRef = oPointer._pRef;
        _pRef->AddRef();
        return *this;
    }
    UPointer& operator=(UClass* pPointer)
    {
        _pRef->RemoveRef();
        _pRef = new UPointerRef(pPointer);
        _pRef->AddRef();
        return *this;
    }
    bool operator==(UClass* pPointer)
    {
        return _pRef->pObject == pPointer;
    }
    bool operator!=(UClass* pPointer)
    {
        return _pRef->pObject != pPointer;
    }
    bool operator !(void)
    {
        return (_pRef->pObject == 0x0);
    }
    operator bool(void)
    {
        return (_pRef->pObject != 0x0);
    }
};
#endif

A smart pointer 旨在提供 ownership 语义,可以对其进行分类(并且具有可用的 c++ 标准实现):

  • 唯一 所有权总是在传递时转移
  • shared 没有单一的所有者,智能指针计数引用,如果这些下降到 0
  • weak 依赖指针,但提供检查引用指针是否仍然有效的能力

这与您的包装器实现完全不同。

A object1;
B object2(A);

Is it possible to do this with any of the smart pointers in std::memory?

使用标准的智能指针,您不会获得深层复制语义。您将拥有浅拷贝语义(std::shared_ptr)或移动语义(std::unique_ptr)。但是,没有什么可以阻止您在 class 中创建一个 clone() 方法 returns 一个智能指针。这样您就可以在需要时获得深拷贝,同时仍然受益于智能指针附带的所有权语义。