Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between operator new() and operator new[]()?

Tags:

c++

memory

Is there any difference between fncs: operator new and operator new[] (NOT new and new[] operators)? Except of course call syntax? I'm asking because I can allocate X number of bytes for my objs with ::operator new(sizeof(T)*numberOfObject) and then access them with array notation, so what's the big deal with ::operator new[]. Is it only syntactic sugar?

#include <new>
#include <iostream>
#include <malloc.h>

using namespace std;
struct X
{
  int data_;
  X(int v):data_(v){}
};
int _tmain(int argc, _TCHAR* argv[])
{
  unsigned no = 10;
  void* vp = ::operator new(sizeof(X) * no);
  cout << "Mem reserved: " << _msize(vp) << '\n';
  X* xp = static_cast<X*>(vp);
  for (unsigned i = 0; i < no; ++i)
  {
    new (xp + i) X(i);
  }
  for (unsigned i = 0; i < no; ++i)
  {
    cout << (xp[i]).data_ << '\n';
  }
  for (unsigned i = 0; i < no; ++i)
  {
    (xp + i)->~X();
  }
  ::operator delete(vp);
  return 0;
}
like image 595
There is nothing we can do Avatar asked Dec 11 '10 17:12

There is nothing we can do


People also ask

What is new () in C?

new() The new operator requests for the memory allocation in heap. If the sufficient memory is available, it initializes the memory to the pointer variable and returns its address.

What is the new operator?

The new operator lets developers create an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

What is difference between new and delete operators?

Difference Between new and delete Operator in C++ In brief, new is an operator in C++ that allocates memory for an object or an array of objects. In contrast, delete is an operator in C++ that deallocates a block of memory previously allocated for an object created using the new operator.

What is new operator with example?

An Example of allocating array elements using “new” operator is given below: int* myarray = NULL; myarray = new int[10]; Here, new operator allocates 10 continuous elements of type integer to the pointer variable myarray and returns the pointer to the first element of myarray.


2 Answers

These functions (operator new etc.) are not generally intended to be called explicitly, but rather used implicitly by new/new[] expressions (symmetrically, operator delete/operator delete[] functions are invoked implicitly by delete/delete[] expressions). An expression that uses new syntax for non-array type will implicitly call operator new function, while an expression with new[] will implicitly call operator new[].

The important detail here is that an array created by new[] expression will normally be destroyed later by delete[] expression. The latter will need to know the number of objects to destruct (if the objects have non-trivial destructors), i.e. this information has to be passed somehow from new[] expression (when it was known) to the corresponding delete[] expression (when it is needed). In a typical implementation this information is stored inside the block allocated by new[] expression, which is why the memory size requested in the implicit call to operator new[] is normally greater than the product of the number of elements and the element size. The extra space is used to store the household information (number of elements, namely). Later delete[] expression will retrieve that household information and use it to invoke the correct number of destructors before actually freeing the memory by calling operator delete[].

In your example you are not using any of these mechanisms. In your example you are calling memory allocation functions explicitly, perform construction manually and completely ignore the destruction step (which is OK, since your object has trivial destructor), which means that at least for destruction purposes you don't need to track the exact number of elements in the array. In any case, you keep track of that number manually, in a no variable.

However, in general case it is not possible. In general case the code will use new[] expressions and delete[] expressions and the number of elements will have to get from new[] to delete[] somehow, meaning that it has to be stored internally, which is why there's a need for a dedicated memory allocation function for arrays - operator new[]. It is not equivalent to a mere operator new with the aforementioned product as size.

like image 176
AnT Avatar answered Nov 06 '22 01:11

AnT


In your example code, you're using placement new to perform the construction that operator new[] performs automatically - with the difference that new[] will only perform default construction and you're performing a non-default placement construction.

The following is more or less equivalent to your example:

#include <iostream>

using namespace std;

struct X
{
    int data_;
    X(int v=0):data_(v){}
};

int main(int argc, char* argv[])
{
    unsigned no = 10;

    X* xp = new X[no];

    for (unsigned i = 0; i < no; ++i) {
        X tmp(i);
        xp[i] = tmp;
    }

    for (unsigned i = 0; i < no; ++i)
    {
        cout << (xp[i]).data_ << '\n';
    }

    delete[] xp;

    return 0;
}

The differences in this example are:

  • I believe the example here is more readable (casts can be ugly, and placement new is a pretty advanced technique that isn't often used, so isn't often understood)
  • it properly destroys the allocated objects (it doesn't matter in the example since the object are PODs, but in the general case, you need to call the dtor for each object in the array)
  • it has to default construct the array of objects, then iterate over them to set the actual value for the object - this is the one disadvantage in this example as opposed to yours

I think that in general, using new[]/delete[] is a much better than allocating raw memory and using placement new to construct the objects. It pushes the complexity of the bookkeeping into those operators instead of having it in your code. However, if the cost of the "default construct/set desired value" pair of operations is found to be too costly, then the complexity of doing it manually might be worthwhile. That should be a pretty rare situation.

Of course, any discussion of new[]/delete[] needs to mention that using new[]/'delete[]should probably be avoided in favor of usingstd::vector`.

like image 38
Michael Burr Avatar answered Nov 06 '22 03:11

Michael Burr