简单包装器 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 A
和 B
,B
的构造函数引用了 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 一个智能指针。这样您就可以在需要时获得深拷贝,同时仍然受益于智能指针附带的所有权语义。
出于教育目的,我今天早些时候实现了一个包装器 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 A
和 B
,B
的构造函数引用了 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 一个智能指针。这样您就可以在需要时获得深拷贝,同时仍然受益于智能指针附带的所有权语义。