编译器警告(等级 1)C4291

'declaration':未找到匹配的删除运算符;如果初始化引发异常,则不会释放内存

放置new运算符用于没有放置删除运算符的位置。

为具有运算符 new 的对象分配内存时,将调用对象的构造函数。 如果构造函数引发异常,则应解除分配为对象分配的任何内存。 除非存在与运算符 new 匹配的运算符 delete 函数,否则无法进行此操作。

如果使用不带任何额外自变量的运算符 new,并用 /GX/EHs 或 /EHs 选项进行编译,则编译器将在构造函数引发异常时生成代码来调用运算符 delete

如果使用 new 运算符的放置形式(除了分配的大小之外,还带有参数的形式) 和对象的构造函数引发异常,则编译器仍将生成调用运算符 delete 的代码;但是,仅当存在与分配内存的运算符 new 的位置形式匹配的运算符 delete 的位置形式时,该运算符才会执行此操作。 例如:

// C4291.cpp
// compile with: /EHsc /W1
#include <malloc.h>

class CList
{
public:
   CList(int)
   {
      throw "Fail!";
   }
};

void* operator new(size_t size, char* pszFilename, int nLine)
{
   return malloc(size);
}

int main(void)
{
   try
   {
      // This will call ::operator new(unsigned int) to allocate heap
      // memory. Heap memory pointed to by pList1 will automatically be
      // deallocated by a call to ::operator delete(void*) when
      // CList::CList(int) throws an exception.
      CList* pList1 = new CList(10);
   }
   catch (...)
   {
   }

   try
   {
      // This will call the overloaded ::operator new(size_t, char*, int)
      // to allocate heap memory. When CList::CList(int) throws an
      // exception, ::operator delete(void*, char*, int) should be called
      // to deallocate the memory pointed to by pList2. Since
      // ::operator delete(void*, char*, int) has not been implemented,
      // memory will be leaked when the deallocation cannot occur.
      CList* pList2 = new(__FILE__, __LINE__) CList(20);   // C4291
   }
   catch (...)
   {
   }
}

上面的示例生成警告 C4291,因为尚未定义与运算符 new 的放置形式匹配的运算符 delete 的放置形式。 若要解决此问题,请在 main 函数上面插入以下代码。 请注意,除第一个参数外,所有重载运算符 delete 函数参数都与重载运算符 new 的函数参数匹配。

void operator delete(void* pMem, char* pszFilename, int nLine)
{
   free(pMem);
}