gpt4 book ai didi

c++ - 避免对非虚拟析构函数进行对象切片

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:25:21 28 4
gpt4 key购买 nike

我正在为智能指针编写代码作为练习。使用在线教程(12)我开发了一个带有引用计数的普通智能指针类。问题是我无法弄清楚以下内容:

when the smart pointer detects that no more references exist to aparticular object, it must delete the object via a pointer to theoriginal type, even if the template argument of the final smartpointer is of a base type. This is to avoid object slicing fornon-virtual destructors.

我怎样才能做到这一点。基本上我的代码如下所示(来自教程)。

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;
}
};

编辑:

为此,我必须有一个指向原始类型的指针。

我在这里发布了一个问题:delete via a pointer to Derived, not Base

但是现在,自从查看评论和答案后,我认为两者都是相关的。我有构造函数:

template <typename T>
template <typename U>
Sptr<T>::Sptr(U* u) : obj(u),ref(NULL) {
//do something
ref = new RC();
ref->AddRef();
}

现在考虑 Sptr<Base1> sp(new Derived);其中 Derived源自 Base1 . Base1 具有 protected 构造函数/析构函数。正在存储 T 类型的对象但是我需要通过 U 类型的对象来存储它。我需要保留它。我该怎么做?

最佳答案

您的智能指针需要 3 个信息 block 。

首先,指向数据的指针(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!
}
}
};

或者类似的东西

关于c++ - 避免对非虚拟析构函数进行对象切片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15886590/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com