我正在考虑我可能写的一些内存池/分配内容,所以我提出了这个operator new
重载,我想用它来促进内存的重用。我想知道你们的实现(或任何其他可能的实现)是否存在任何问题。
#include <cstddef>
namespace ns {
struct renew_t { };
renew_t const renew;
}
template<typename T>
inline void * operator new(std::size_t size, T * p, ns::renew_t renew_constant) {
p->~T();
return p;
}
template<typename T>
inline void operator delete(void *, T *, ns::renew_t renew_constant) { }
可以像这样使用
int main() {
foo * p(new foo()); // allocates memory and calls foo's default constructor
new(p, ns::renew) foo(42); // calls foo's destructor, then calls another of foo's constructors on the same memory
delete p; // calls foo's destructor and deallocates the memory
}
答案 0 :(得分:2)
请阅读http://www.gotw.ca/gotw/022.htm和http://www.gotw.ca/gotw/023.htm。
实际上,您应该定义operator=
而不是使用析构函数来玩游戏。在混合中添加operator new
(和operator delete
,YUCK!)重载只会增加痛苦。
而且,正如C ++神Herb Sutter在这些链接中所建议的那样,你可以简单地用operator=
来定义构造函数。
答案 1 :(得分:1)
应该是好的,只要你不尝试疯狂的东西并尝试更新子类。既然你说这是一个游泳池,那应该没事。
那就是说,我唯一的问题是 - 什么更清晰?这是一个品味问题,但想象一下其他人可能需要查看代码。您基本上只是将两个简单明了的语句合并为一个,需要更深入地了解代码内部的功能。
在我的游泳池功能中,我通常有两种不同的方法,一种是销毁,一种是构造,它们基本上都是你在这里做的(p-&gt; ~T和new(p)T()),但是至少你完全知道他们做了什么。
答案 2 :(得分:0)
delete()
运算符不会调用对象的析构函数,这对我来说是意料之外的。
我必须对new(p, ns::renew) foo(42)
进行双重拍摄。对我而言,这根本不直观。
您可能真正想要的是分离内存分配和构建对象的过程。对于这种情况,通常使用"placement new"代替。
// Not exception safe!
void* p = ::operator new(sizeof(T)); // allocate raw memory
new(p) T(41); // construct a T at this memory location
p->~T(); // destruct T
new(p) T(42); // recreate a different T at the same memory location
p->~T(); // destruct T
::operator delete(p); // deallocate raw memory
在实际内存池应用程序中,您可以wrap the above lines into a MemoryPool
class of some sort.
当然,这仅适用于您实际直接处理内存以实现实际内存池或容器的分配器的情况。在其他情况下,you're better off overloading the =
operator() as suggested by Potatoswatter。