Export (0) Print
Expand All

The new and delete Operators

C++ supports dynamic allocation and deallocation of objects using the new and delete operators. These operators allocate memory for objects from a pool called the free store. The new operator calls the special function operator new, and the delete operator calls the special function operator delete.

Beginning in Visual C++ .NET 2002, the CRT's new function (in libc.lib, libcd.lib, libcmt.lib, libcmtd.lib, msvcrt.lib, and msvcrtd.lib) will continue to return NULL if memory allocation fails. However, the new function in the Standard C++ Library (in libcp.lib, libcpd.lib, libcpmt.lib, libcpmtd.lib, msvcprt.lib, and msvcprtd.lib) will support the behavior specified in the C++ standard, which is to throw a std::bad_alloc exception if the memory allocation fails.

Normally, if you #include one of the C++ standard headers, like <new>, you'll get a /defaultlib directive in your object that will reference the appropriate C++ Standard Library according to the CRT model you used (the /M* compiler options). Generally, that will cause the linker to use the throwing operator new from the C++ Standard Library instead of the nonthrowing one from the main CRT, because the order of defaultlib directives will cause libcp.lib to be searched before libc.lib (under /ML).

Even if you use one of the C++ standard library headers, it is possible to get non-throwing new. For example, compile the program below with the following command line and you will not get throwing new behavior, even though standard C++ header files are included:

cl /EHsc new_and_delete.cpp libc.lib libcp.lib

To ensure that you get the throwing version of new, link your program with thrownew.obj. In the following example, you can get throwing new behavior if you link with thrownew.obj.

cl /EHsc new_and_delete.cpp libc.lib libcp.lib thrownew.obj

Linking with thrownew.obj is only required for special circumstances where, for some reason, the linker used the non-throwing new from libc instead of the throwing one from libcp. The normal reason for the non-throw new being used is that you link with /nodefaultlib libc.lib libcp.lib. That is, you turned off the defaultlib directives that specifies what libs to use, and instead specified them manually, putting the normal CRT lib before the C++ Standard Lib. So, you can either change the command line so libcp is specified first, or add thrownew.obj explicitly.

Note   You should always link with thrownew.obj when compiling from the Visual Studio development environment to ensure the correct behavior.
// new_and_delete.cpp
// compile with: /EHsc
#include <stdio.h>
#include <new>
#include <limits.h>
int main()
{
   int * i_arr;
   try {
      i_arr = new int[0x3fffffff];
   } 
   catch(...) {
      printf("caught exception\n");
   }

   int * k_arr;
   k_arr = new (std::nothrow) int[0x3fffffff];

   delete[] i_arr;   // vector delete
   delete[] k_arr;
}

Note the use of std::nothrow in the previous example. This allows your code to have expected (non-throwing new) behavior, even when your code is linked with either version of new. By doing this, you will not rely on getting the non-throwing ::operator new(size_t) from libc.lib instead of the throwing version of the same routine from libcp.lib. This is especially useful when writing third-party .libs. If you create a .lib that doesn't have dependencies on libcp or other Standard C++ Libraries, you cannot be sure that when your .lib is used to create a .exe/.dll you'll end up getting the operator new from libc or libcp, so if you call the normal non-placement operator new, you don't know if you'll eventually get the throwing or non-throwing version. So to work around that, make sure, if you want the non-throwing new, to use the placement-new form with std::nothrow.

See Also

Special Member Functions

Show:
© 2014 Microsoft