gpt4 book ai didi

c++ - 使用类型删除在 C++11 中删除 void*

转载 作者:行者123 更新时间:2023-11-30 04:01:20 25 4
gpt4 key购买 nike

我正在尝试修复此类中的双重释放或损坏:

struct Holder
{
template <typename T>
Holder(const T& v)
{
_v = new T{};
memcpy(_v, &v, sizeof(T));

_deleter = [this]{
if (_v != nullptr)
{
delete reinterpret_cast<T*>(_v);
_v = nullptr;
}
};
}

template <typename T>
T get()
{
T t;
memcpy(&t, _v, sizeof(T));
return t;
}

~Holder()
{
std::cout << "~Holder() " << std::endl;
_deleter();
}

private:
void* _v;
std::function<void()> _deleter;
};

这个类的目标是保存一个特定类型的值,比如boost::any。所以我试图了解安全释放所有内存的机制。

大概是这行代码:

delete reinterpret_cast<T*>(_v);

没有达到我的预期......

**** 建议后 ****

我使用评论建议重写了代码并添加了一个移动构造函数

struct Holder
{
template <typename T>
Holder(const T& v)
{
std::cerr << "create " << N << std::endl;
_v = new T(v);

_deleter = [this]{
if (_v != nullptr)
{
std::cerr << "deleter " << N << std::endl;
delete reinterpret_cast<T*>(_v);
_v = nullptr;
}
};
}


Holder(Holder&& rs)
{
_v = rs._v;
_deleter = std::move(rs._deleter);
rs._deleter = []{}; //usefull to avoid a bad function call
}


template <typename T>
T get() const
{
return *reinterpret_cast<T*>(_v);
}

~Holder()
{
//std::cout << "~Holder() " << N << std::endl;
_deleter();
}

private:
void* _v;
std::function<void()> _deleter;
};

现在似乎可行,但我必须管理其他极端情况 :)可能最好的解决方案是使用 boost::any:

struct Holder
{
template <typename T>
Holder(const T& v)
{
_v = v;
}

template <typename T>
T get()
{
return boost::any_cast<T>(_v);
}

private:
boost::any _v;
};

但我想了解没有它它是如何工作的。

这是我的最后一个版本:

struct Holder
{
template <typename T>
Holder(const T& v)
{
std::cerr << "create " << N << std::endl;
_v = new T(v);

_deleter = [](void* ptr){
if (ptr != nullptr)
{
std::cerr << "deleter " << std::endl;
delete reinterpret_cast<T*>(ptr);
}
};

_builder = [](void* &dest, void* src){
dest = new T(*reinterpret_cast<T*>(src));
};
}

Holder(const Holder& rs)
{
std::cerr << "copy constr" << std::endl;
if (this != &rs)
{
rs._builder(_v, rs._v);
_deleter = rs._deleter;
_builder = rs._builder;
}
}

Holder(Holder&& rs)
{
std::cerr << "move constr" << std::endl;
if (this != &rs)
{
_v = rs._v;
_deleter = std::move(rs._deleter);
_builder = std::move(rs._builder);
rs._deleter = [](void*){};
}
}

Holder& operator=(const Holder& rs)
{
std::cerr << "copy operator" << std::endl;
if (this != &rs)
{
rs._builder(_v, rs._v);
_deleter = rs._deleter;
_builder = rs._builder;
}

return *this;
}

Holder& operator=(Holder&& rs)
{
std::cerr << "move operator" << std::endl;
if (this != &rs)
{
_v = rs._v;
_deleter = std::move(rs._deleter);
_builder = std::move(rs._builder);
rs._deleter = [](void*){};
}

return *this;
}

template <typename T>
T get() const
{
return *reinterpret_cast<T*>(_v);
}

~Holder()
{
//std::cout << "~Holder() " << N << std::endl;
_deleter(_v);
}

private:
void* _v;
std::function<void(void* ptr)> _deleter;
std::function<void(void* &, void* src)> _builder;
};

最佳答案

不要重新实现这匹马。

using pvoid_holder = std::unique_ptr<void, std::function<void(void*)>>
template<class T>
pvoid_holder pvoid_it( T* t ) {
return { t, [](void* v){ if (v) delete static_cast<T*>(v); } };
}

现在在您的Holder 类中存储一个pvoid_holder。它将为您处理内存生命周期。

您可以使用裸pvoid_holder,但它可能有比您想要的更丰富的接口(interface)(例如,它允许在不更改删除器的情况下更改存储的指针)。

您还可以将 std::function 替换为 void(*)(void*) 以获得边际性能增益。

关于c++ - 使用类型删除在 C++11 中删除 void*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25835185/

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