简单包装类与智能指针



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

#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

其主要思想是充当指针,同时还具有处理内存管理、复制构造函数、析构函数和赋值运算符的额外优势。它包装具有克隆方法的类:它们返回一个指向自身副本的指针(而不是指向自身,指向用newClass(*this)创建的新副本)。

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

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

A object1;
B object2(A);

这是因为object2用于使用上述Wrapper构造函数来构造Wrapper< A >(然后传递给B的构造函数)。

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

智能指针旨在提供所有权语义,这些语义可以分类(并且与可用的c++标准实现一起):

  • 唯一 所有权总是在传递时转移
  • 共享 没有单个所有者,智能指针计算引用数,如果引用数为0,则会进行递减
  • weak 一个依赖指针,但可以检查引用的指针是否仍然有效

这与您的包装器实现非常不同。

是的,所有这些都是可能的。。供参考。。因为有一次我也实现了类似的东西。。(也用于教育目的)。。我可以分享我为智能指针制作的代码,并进行引用计数。。这意味着你可以创建任意数量的副本,当最后一个副本被销毁时,它将删除对象
#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 object1;
B object2(A);

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

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

最新更新