The three USES of new in c++ are explained in detail

  • 2020-04-02 01:40:51
  • OfStack

A brief introduction.
There are three ways to use new: plain new, nothrow new, and placement new.

(1) as the name implies, the plain new is the ordinary new, which is the new we used to use. In C++, it is defined as follows:
      Void * operator new (STD: : size_t) throw (STD: : bad_alloc);
      Void operator delete(void *) throw();

Tip: The plain new throws an exception STD ::bad_alloc instead of returning NULL in the case of an allocation failure, so it is futile to determine whether the return value is NULL.

(2) nothrow new is the form of the operator new that does not throw an exception. Nothrow new returns NULL on a failure. The definition is as follows:
      Void * operator new(STD ::size_t,const STD ::nothrow_t&) throw();
      Void operator delete (void *) throw ();

(3) placement new, which allows you to rebuild an object or an array of objects on a block of memory that has been successfully allocated. Placement new doesn't have to worry about memory allocation failure because it doesn't allocate memory at all and the only thing it does is call the constructor of the object. The definition is as follows:
      Void * operator new (size_t, void *);
      Void operator delete (void *, void *).

Hint 1: The main use of palcement new is to repeatedly use a large block of dynamically allocated memory to construct different types of objects or their arrays.

Tip 2: Placement new constructs objects or their arrays to be displayed are destroyed by calling their destructors, never use delete.

Char * p = new(nothrow) char[100];
Long *q1 = new(p) long(100);
Int *q2 = new(p) int[100/sizeof(int)];

Example 2.

1. Plain new/delete
The definition is as follows:
Void * operator new (STD: : size_t) throw (STD: : bad_alloc);
Void operator delete (void *) throw ();

Note: The standard C++ plain new fails to throw the standard exception STD ::bad_alloc instead of returning NULL, so it is futile to check if the return value is NULL to see if the allocation was successful.

Test procedures:


#include "stdafx.h"
#include <iostream>
using namespace std;
char *GetMemory(unsigned long size)
{
char *p=new char[size];//Allocation failed, not NULL returned
return p;
}
int main()
{
try
{
  char *p=GetMemory(10e11);//An allocation failure throws an exception STD ::bad_alloc
  //...........
  if(!p)//In vain
   cout<<"failure"<<endl;
  delete [] p;
}
catch(const std::bad_alloc &ex)
{
  cout<<ex.what()<<endl;
}

    return 0;
}

2. Nothrow new/delete does not throw an exception in the form of the operator new, which returns NULL when it fails.
The definition is as follows:

void *operator new(std::size_t,const std::nothrow_t&) throw();
void operator delete(void*) throw();
struct nothrow_t{};  const nothrow_t nothrow;//Nothrow is the signature dummy of new

Test procedures:

#include "stdafx.h"
#include <iostream>
#include <new>
using namespace std;
char *GetMemory(unsigned long size)
{
char *p=new(nothrow) char[size];//NULL was returned when the assignment failed
if(NULL==p)
  cout<<"alloc failure!"<<endl;
return p;
}
int main()
{
try
{
  char *p=GetMemory(10e11);
  //...........
  if(p==NULL)
   cout<<"failure"<<endl;
  delete [] p;
}
catch(const std::bad_alloc &ex)
{
  cout<<ex.what()<<endl;
}

    return 0;
}

The main use of placement new/delete is to repeatedly use a large block of dynamically allocated memory to construct different types of objects or arrays of them. For example, you can apply for a large enough array of characters and then construct different types of objects or arrays on it as needed. Placement new doesn't have to worry about memory allocation failure because it doesn't allocate memory at all, it just calls the constructor of the object.

Test procedures:


#include "stdafx.h"
#include <iostream>
#include <new>
using namespace std;
class ADT
{
int i;
int j;
public:
ADT()
{
}
~ADT()
{
}
};
int main()
{
char *p=new(nothrow) char[sizeof(ADT)+2];
if(p==NULL)
  cout<<"failure"<<endl;
ADT *q=new(p) ADT;  //Don't worry about failing
// delete q;// error ! It cannot be called here delete q;
q->ADT::~ADT();//Shows the call to the destructor
delete []p;
    return 0;
}

Note: Use the placement of new structure of object or array, to explicitly call their destructor to destroy (the destructor does not release the memory object), never use the delete. This is because the placement of new structure of object or the array size is not necessarily equal to the original allocation of memory size, use the delete will cause memory leak or free memory after a runtime error.


Related articles: