Tutorial on the use of C++ operators in programming

  • 2020-05-07 20:12:08
  • OfStack

The new operator is used to allocate memory from objects or arrays of objects that are freely stored as type-name and to return properly sorted non-zero Pointers to objects.


[::] new [placement] new-type-name [new-initializer]
[::] new [placement] ( type-name ) [new-initializer]

note
If
fails, new returns zero or throws an exception. For more information, see the new and delete operators. You can change this default behavior by writing a custom exception handler routine and calling the _set_new_handler runtime function (with your function name as its argument).
For information on how to create objects on the managed heap, see gcnew.
When new is used to allocate memory for C++ class objects, the object's constructor is called after memory is allocated.
Using the delete operator disallocates memory allocated using the new operator.
The following example allocates and then frees a 2-dimensional character array of size dim x 10. When assigning a multidimensional array, all dimensions except the first dimension must be constant expressions with positive results. The leftmost array dimension can be any expression that evaluates to a positive value. When an array is allocated using the new operator, the first dimension can be zero - the new operator returns a unique 1 pointer.


char (*pchar)[10] = new char[dim][10];
delete [] pchar;

type-name cannot contain const, volatile, class declarations, or enumeration declarations. Therefore, the following expression is illegal:


volatile char *vch = new volatile char[20];

The new operator does not assign reference types because they are not objects.
The new operator cannot be used to assign functions, but can be used to assign Pointers to functions. The following example allocates a function that returns an integer and then releases an array that contains seven Pointers.


int (**p) () = new (int (*[7]) ());
delete *p;

If you use the new operator with no additional arguments and compile with /GX, /EHa, or /EHs options, the compiler generates code to call the operator delete when the constructor throws an exception.
The following list describes the syntax elements of new:
placement
If new is overloaded, a way to pass additional parameters is provided.
type-name
Specifies the type to assign; It can be a built-in type or a user-defined type. If the type specification is very complex, you can enclose it in parentheses to enforce the binding order.
initializer
Provides a value for the initialization object. Cannot specify an initializer for an array. The new operator creates an array of objects only if the class has a default constructor.
sample
The following code example allocates a 1-character array and an object of class CName and then frees them.


// expre_new_Operator.cpp
// compile with: /EHsc
#include <string.h>

class CName {
public:
  enum {
   sizeOfBuffer = 256
  };

  char m_szFirst[sizeOfBuffer];
  char m_szLast[sizeOfBuffer];

public:
  void SetName(char* pszFirst, char* pszLast) {
   strcpy_s(m_szFirst, sizeOfBuffer, pszFirst);
   strcpy_s(m_szLast, sizeOfBuffer, pszLast);
  }

};

int main() {
  // Allocate memory for the array
  char* pCharArray = new char[CName::sizeOfBuffer];
  strcpy_s(pCharArray, CName::sizeOfBuffer, "Array of characters");

  // Deallocate memory for the array
  delete [] pCharArray;      
  pCharArray = NULL;

  // Allocate memory for the object
  CName* pName = new CName;
  pName->SetName("Firstname", "Lastname");

  // Deallocate memory for the object
  delete pName;
  pName = NULL;
}

The compiler does not support the placement of the delete operator if it USES the new placement form of the new operator (in the form with arguments and assigned sizes) and if the constructor throws an exception. Such as:


// expre_new_Operator2.cpp
// C2660 expected
class A {
public:
  A(int) { throw "Fail!"; }
};
void F(void) {
  try {
   // heap memory pointed to by pa1 will be deallocated
   // by calling ::operator delete(void*).
   A* pa1 = new A(10);
  } catch (...) {
  }
  try {
   // This will call ::operator new(size_t, char*, int).
   // When A::A(int) does a throw, we should call
   // ::operator delete(void*, char*, int) to deallocate
   // the memory pointed to by pa2. Since
   // ::operator delete(void*, char*, int) has not been implemented,
   // memory will be leaked when the deallocation cannot occur.

   A* pa2 = new(__FILE__, __LINE__) A(20);
  } catch (...) {
  }
}

int main() {
  A a;
}

initializes the object assigned using the new operator
The optional initializer field for
is contained in the syntax of the new operator. This allows you to initialize the new object using a user-defined constructor. For more information on how to perform initialization, see the initializer. The following example shows how to use an initialization expression with the new operator 1:


// expre_Initializing_Objects_Allocated_with_new.cpp
class Acct
{
public:
  // Define default constructor and a constructor that accepts
  // an initial balance.
  Acct() { balance = 0.0; }
  Acct( double init_balance ) { balance = init_balance; }
private:
  double balance;
};

int main()
{
  Acct *CheckingAcct = new Acct;
  Acct *SavingsAcct = new Acct ( 34.98 );
  double *HowMuch = new double ( 43.0 );
  // ...
}

In this example, objects are assigned using the CheckingAcctnew operator, but default initialization is not specified. Therefore, the default constructor Acct() of the class is called. The object SavingsAcct is then assigned in the same way, except that it is explicitly initialized to 34.98. Since 34.98 is of type double, the constructor that takes the argument of that type is called to handle the initialization. Finally, the non-class type HowMuch is initialized to 43.0.
If the object is a class type and has a constructor (as shown in the previous example), the new operator can initialize the object only if one of the following conditions is met:
The parameters provided in the initializer correspond to the parameters 1 of the constructor.
This class has a default constructor (a constructor that can be called without arguments).
Access control and 2 sense control are performed according to the rule pairs and constructors described in operator new polysemy and initialization using special member functions.
When assigning an array using the new operator, you cannot explicitly initialize each element; Only the default constructor, if any, is called. For more information, see default parameters.
If the memory allocation fails (operator new returns a value of 0), no initialization is performed. This prevents attempts to initialize data that does not exist.
Like function call 1, the order in which the initialization expression is evaluated is not defined. In addition, you should not expect these expressions to be fully evaluated before memory allocation is performed. If the memory allocation fails and the new operator returns zero, some expressions in the initializer may not be fully evaluated.
Lifetime of an object assigned using the new operator
Objects assigned with the new operator are not destroyed when they exit the definition scope. Because the new operator returns Pointers to the objects it assigns, the program must define Pointers with the appropriate scope to access those objects. Such as:


// expre_Lifetime_of_Objects_Allocated_with_new.cpp
// C2541 expected
int main()
{
  // Use new operator to allocate an array of 20 characters.
  char *AnArray = new char[20];

  for( int i = 0; i < 20; ++i )
  {
    // On the first iteration of the loop, allocate
    // another array of 20 characters.
    if( i == 0 )
    {
      char *AnotherArray = new char[20];
    }
  }

  delete [] AnotherArray; // Error: pointer out of scope.
  delete [] AnArray;   // OK: pointer still in scope.
}

In the above example, the pointer AnotherArray 1 cannot delete an object once it is out of range.

The way new works
allocation-expression (an expression containing the new operator) performs three types of operations:
Locate and retain the storage of the object to be allocated. When this stage is complete, the correct amount of storage is allocated, but it is not yet an object.
Initializes the object. When the initialization is complete, enough information is displayed for the allocated store to become an object.
Returns a pointer to an object of pointer type derived from new-type-name or type-name. The program USES this pointer to access the most recently allocated object.
The new operator calls the function operator new. For arrays of any type and objects that are not of type class, struct, or union, the global function ::operator new is called to allocate storage. A class-type object can define its own operator new static member function based on each class.
When the compiler encounters the new operator used to assign objects of type type, it makes a call to type::operator new(sizeof(type)). Or, if there is no user-defined operator new, call ::operator new(sizeof(type)). Therefore, the new operator can assign the correct amount of memory to an object.


Related articles: