我一直在阅读有关重载新的和删除(以及相关主题,如放置新/删除).到目前为止,令我困惑的一件事是operator delete的标准签名是(在类范围内):
void operator delete(void *rawMemory, std::size_t size) throw();
Run Code Online (Sandbox Code Playgroud)
删除的方式如下:
MyClass* ptr = new MyClass;
delete ptr;
Run Code Online (Sandbox Code Playgroud)
那么,如何delete ptr;为大小提供第二个参数?另外,在这种情况下,我可以假设MyClass*被隐式转换为void*吗?
Alo*_*ave 10
new并且delete在类范围内重载运算符以优化特定类对象的分配.但是由于某些特殊情况Inheritance可能导致分配请求超过类大小本身,因此可能存在特殊情况.由于new和delete重载的目的是对大小的对象进行特殊调整sizeof(Base),没有更大或更小,这些重载的运算符应该转发所有其他wrong sized内存请求,::operator new并且::operator delete能够这样做,size参数需要作为参数传递.
考虑一个特殊情景:
class Base
{
public:
static void * operator new(std::size_t size) throw(std::bad_alloc);
};
class Derived: public Base
{
//Derived doesn't declare operator new
};
int main()
{
// This calls Base::operator new!
Derived *p = new Derived;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,由于继承,派生类Derived继承了该类的new运算符Base.这使得在基类中调用operator new可以为派生类的对象分配内存.我们的操作员new处理这种情况的最佳方法是将请求"错误"内存量的此类调用转移到标准运算符new,如下所示:
void * Base::operator new(std::size_t size) throw(std::bad_alloc)
{
if (size != sizeof(Base)) // if size is "wrong," i.e != sizeof Base class
{
return ::operator new(size); // let std::new handle this request
}
else
{
//Our implementation
}
}
Run Code Online (Sandbox Code Playgroud)
在重载delete运算符时,One还必须确保由于特定于类的运算符新转发"错误"大小的请求,因此::operator new必须将"错误大小"的删除请求转发到:: operator delete,因为原始运算符保证要处理这些请求以符合标准的方式提出.
所以自定义delete运算符将是这样的:
class Base
{
public:
//Same as before
static void * operator new(std::size_t size) throw(std::bad_alloc);
//delete declaration
static void operator delete(void *rawMemory, std::size_t size) throw();
void Base::operator delete(void *rawMemory, std::size_t size) throw()
{
if (rawMemory == 0)
{
return; // No-Op is null pointer
}
if (size != sizeof(Base))
{
// if size is "wrong,"
::operator delete(rawMemory); //delegate to std::delete
return;
}
//If we reach here means we have correct sized pointer for deallocation
//deallocate the memory pointed to by rawMemory;
return;
}
};
Run Code Online (Sandbox Code Playgroud)
进一步阅读:
以下C++ - Faq条目讨论了以标准兼容的方式重载new和delete,并且可能是一个很好的阅读:
我应该如何编写iso c ++标准符合自定义新的和删除运算符?
那么,如何删除ptr; 提供尺寸的第二个参数?
如果指针类型是具有虚拟析构函数的类类型,则来自有关对象类型的动态信息.如果它没有虚拟析构函数并且指针类型匹配指针类型 - 来自编译时间信息有关类型大小.否则delete ptr是未定义的行为.