foo*_*oty 5 c++ templates pointers g++ smart-pointers
我正在为智能指针编写代码作为练习.使用在线教程(1,2)我已经与引用计数正常的智能指针类.问题是我无法弄清楚以下内容:
当智能指针检测到特定对象不再存在引用时,它必须通过指向原始类型的指针删除该对象,即使最终智能指针的模板参数是基类型也是如此.这是为了避免非虚拟析构函数的对象切片.
我怎样才能做到这一点.基本上我的代码如下所示(来自教程).
template < typename T > class SP
{
private:
T* pData; // pointer
RC* reference; // Reference count
public:
SP() : pData(0), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(T* pValue) : pData(pValue), reference(0)
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
SP(const SP<T>& sp) : pData(sp.pData), reference(sp.reference)
{
// Copy constructor
// Copy the data and reference pointer
// and increment the reference count
reference->AddRef();
}
~SP()
{
// Destructor
// Decrement the reference count
// if reference become zero delete the data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
}
T& operator* ()
{
return *pData;
}
T* operator-> ()
{
return pData;
}
SP<T>& operator = (const SP<T>& sp)
{
// Assignment operator
if (this != &sp) // Avoid self assignment
{
// Decrement the old reference count
// if reference become zero delete the old data
if(reference->Release() == 0)
{
delete pData;
delete reference;
}
// Copy the data and reference pointer
// and increment the reference count
pData = sp.pData;
reference = sp.reference;
reference->AddRef();
}
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
编辑:
要实现这一点,我必须有一个指向原始类型的指针.
我在这里发了一个问题:通过指向Derived的指针删除,而不是Base
但是现在查看评论和答案后我认为两者都是相关的.我有构造函数:
template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}
Run Code Online (Sandbox Code Playgroud)
现在考虑从Sptr<Base1> sp(new Derived);哪里Derived得到Base1.Base1具有受保护的构造函数/析构函数.哪个是存储类型的对象T但我需要通过U类型的对象存储它.我需要保留它.我怎样才能做到这一点?
您的智能指针需要3块信息.
首先,指向数据(T*或某事)的指针.
第二,你的引用数:std::atomic<int>或者其他什么.
第三,你的破坏功能(std::function<void(T*)>或其他东西).
首次创建智能指针时,会创建该销毁功能.将智能指针复制到另一个智能指针时,将复制此销毁功能.如果新智能指针的类型与旧指针不匹配,那么该销毁函数将以类型兼容的方式进行封装(std::function<void(Base*)> = std::function<void(Derived*)>开箱即用?无论如何,您基本上都是这样做的).
默认情况下,此销毁功能只是delete t,但作为附带好处,这允许智能指针的用户传递销毁功能,这并非总是如此delete t.
有趣的是,相当于reset你,你可以替换你的销毁功能.所以你实际上可以使销毁函数的签名成为std::function<void()>,这使得在它之间移动T并U输入智能指针更容易.
template < typename T > class SP
{
private:
T* pData; // pointer
RC* reference; // Reference count
std::function<void()> destroyData;
public:
template<typename U>
SP(U* pValue):
pData(pValue),
reference(nullptr),
// store how to destroy pValue now, for later execution:
destroyData([pValue]()->void{
delete pValue;
})
{
// Create a new reference
reference = new RC();
// Increment the reference count
reference->AddRef();
}
// similar for operator=, and you may have to do something for SP<T> as well:
template<typename U>
SP(const SP<U>& sp):
pData(sp.pData),
reference(sp.reference),
destroyData(sp.destroyData)
{
// Copy constructor
// Copy the data and reference pointer
// and increment the reference count
reference->AddRef();
}
template<typename U>
SP<T>& operator = (const SP<U>& sp)
{
// blah blah blah, then
destroyData = sp.destroyData;
}
~SP()
{
// Destructor
// Decrement the reference count
// if reference become zero delete the data
if(reference->Release() == 0)
{
delete reference;
destroyData(); // here I destroyed it!
}
}
};
Run Code Online (Sandbox Code Playgroud)
或类似的东西