简单包装类与智能指针

时间:2017-02-02 19:45:53

标签: c++ wrapper shared-ptr

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

#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

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

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

这很方便。假设我们有AB类,B的构造函数会引用Wrapper< A >。然后我可以用另一个对象B构建一个对象A

A object1;
B object2(A);

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

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

3 个答案:

答案 0 :(得分:5)

智能指针旨在提供所有权语义,可以对其进行分类(并使用可用的c ++标准实现):

  • 唯一 所有权在传递时始终传输
  • 共享 没有单一所有者,智能指针计数引用,如果这些属性降至0则会死亡
  • 依赖指针,但能够检查引用指针是否仍然有效

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

答案 1 :(得分:1)

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

#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

答案 2 :(得分:1)

A object1;
B object2(A);
  

是否可以使用std :: memory中的任何智能指针执行此操作?

使用标准智能指针,您将无法获得深层复制语义。您将具有浅复制语义(使用std :: shared_ptr)或移动语义(使用std :: unique_ptr)。但是,没有什么可以阻止您在类中创建返回智能指针的clone()方法。这样,您可以在需要时获得深层副本,同时仍然可以从智能指针附带的所有权语义中受益。