C++ C++;11内存池类-从void*进行静态_转换的解决方法?
我想要一个类C++ C++;11内存池类-从void*进行静态_转换的解决方法?,c++,c++11,C++,C++11,我想要一个类p,它有一个静态delete\u all成员函数,该函数将删除p类型或从p派生的类型的所有动态分配的实例 以下是我所拥有的: #include <unordered_set> using namespace std; struct P { static unordered_set<P*> pool; static void* operator new(size_t size) { void* p = ::operat
p
,它有一个静态delete\u all
成员函数,该函数将删除p
类型或从p
派生的类型的所有动态分配的实例
以下是我所拥有的:
#include <unordered_set>
using namespace std;
struct P
{
static unordered_set<P*> pool;
static void* operator new(size_t size)
{
void* p = ::operator new(size);
pool.insert(static_cast<P*>(p));
return p;
}
static void operator delete(void* p)
{
pool.erase(static_cast<P*>(p));
::operator delete(p);
}
static void delete_all()
{
while (!pool.empty())
delete *(pool.begin());
}
virtual ~P() {}; // polymorphic
};
unordered_set<P*> P::pool;
我关心的部分是静态地将void*
指针转换为p*
。我有一种感觉,在某些情况下,这将导致未定义的行为,例如,在派生类上调用new时,P基类子对象不从派生类的开头开始。内存块还不知道它是派生类的类型,因此来自void的static\u cast
不会给出P子对象的正确位置
这是个问题,我说得对吗?我怎样才能修好它
另外,
p
是否还有一个我不知道的问题?您的静态类型转换是一个问题,这是正确的,原因与您描述的完全相同
除非我遗漏了一些明显的东西,否则您不需要整个操作员new/operator delete舞蹈。只要让P的构造函数在池中存储此,然后P的析构函数将其从池中删除即可。这样,您总是能够处理诚实的P*指针。确保在所有构造函数中都这样做(回想一下,如果您没有明确提供或禁用构造函数,编译器将生成复制和移动构造函数)。我见过的一种技术涉及跟踪
操作符new
中新增的内容,当我们有一个有效的指针时,在构造函数中执行池:该指针将位于void*
和void*+size\t
之间。但是,您的new
是否会在new-Derived
中调用?您也可以使用动态转换(ptr)
构造。这将确保您获得正确的指针,或者在强制转换失败时返回NULL。但是,这不是免费的,因为此转换是在运行时完成的。@Yakk:“但是,您的新代码会在新派生中调用吗?”我不明白您在问什么。是的,由新派生的
生成的动态分配对象应添加到池中,如果尚未添加,则由删除所有
删除。@Xaqq:我认为这不起作用,因为返回的内存块::operator new(字节)
中还没有必要的类型信息来支持dynamic\u cast
@Xaqq:不,您不能dynamic\u cast
将类型为void*
的表达式转换为任何指针类型。参见5.2.7.2他有一个显式定义的析构函数,因此不会生成移动构造函数。
struct D : P
{
...
};
int main()
{
D d1;
D* d2 = new D();
D* d3 = new D();
delete d2;
P::delete_all(); // deletes d3, but not d1 or d2
}