Wednesday 1 December 2010

Difference between 'new', 'new operator' and 'operator new' in C++

A question asked in a forum said:

Why does void* p = new (1024); gives me a compilation error while void* p = operator new (1024); works. What is the difference between new and "operator new"?

Lets go back to the beginning. Once upon a time there was this C language that used 'malloc' to allocate memory. Then when C++ came, a new way was defined of allocating memory by the use of 'new'. Its supposed to be much safter and better way but some software gurus may differ. Memory for 'new' is allocated from 'Free Store' and memory by 'malloc' is generated from 'heap'. The 'heap' and 'Free Store' may be the same area and is a compiler implementation detail.

The syntax for 'operator new' is:
void* new (std::size_t size);

All it does is allocate a memory of size specified

On the other hand, 'new' does 2 things:
1. It calls 'operator new'
2. It calls constructor for the type of object

In the above case since 1024 is not a type, it will fail in calling its constructor.

'new' is also referred to as 'keyword new' or 'new operator' to cause more confusion :)

Here is a small example to play with 'operator new' after the example you will realise that regardless of what is passed, it always allocates a 4 byte memory.



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
#include<iostream>

using namespace
std;

int
main()
{

//void* p = new (1024);

void
* p = operator new (1024);

//Lets test if we can do anything with the memory
cout<<"p = "<<p<<endl;
cout<<"sizeof(p) = "<<sizeof(p)<<endl;
int
*x = static_cast<int *>(p);
cout<<"*x before = "<<*x<<endl;
*
x = 23456;
cout<<"*x after = "<<*x<<endl;

void
* q = operator new (0);
cout<<"\nq = "<<q<<endl;
cout<<"sizeof(q) = "<<sizeof(q)<<endl;
x = static_cast<int *>(q);
cout<<"*x before = "<<*x<<endl;
*
x = 65432;
cout<<"*x after = "<<*x<<endl;

void
* z = operator new ('a');
cout<<"\nz = "<<z<<endl;
cout<<"sizeof(z) = "<<sizeof(z)<<endl;
x = static_cast<int *>(z);
cout<<"*x before = "<<*x<<endl;
*
x = 11111;
cout<<"*x after = "<<*x<<endl;

return
0;
}


The output is as follows:


My knowledge in this area is quite limited so please feel free to improve on my explanation or correct it.

1 comment:

  1. Ok, this entry is over a year old, but I'd like to make a couple of corrections.

    'new' is not referred to as 'new operator'. It is actually called the 'new expression'.

    When you write this:

    new T; // 'new expression', where T is a type

    that in turn, calls operator new (sizeof(T)) and then it calls the constructor of T, if there's any (T might be a built-in type like int).

    So, when you do this:

    void* p = operator new (1024);

    you're just skipping the 'middleman' and calling operator new directly (more or less as the 'new expression' would have), which you shouldn't do, for a number of reasons, but the thing is, it does allocate 1024 bytes.

    The example you provided is not correct, because sizeof ptr does not return the number of bytes allocated, but the size of ptr itself. Under a 32-bit system, it most likely is 4 bytes. You can even try this:

    void* p = malloc(1024);

    which of course, allocates 1024 bytes, and then

    cout << sizeof p << endl;

    and it will also print '4'. There is no way to know, inside a program, the number of bytes allocated for a pointer. But you can tell if malloc(1024) allocated 1024 bytes by checking if it returned a NULL pointer. And you can tell if operator new (1024) succeeded in allocating 1024 bytes, because otherwise it would throw an exception.

    Finally, the reason void* p = new (1024); fails is not because it can't call the constructor, but because the 'new expression' expects a type. That's why it is a compile-time error (it doesn't have a chance to 'try' to call a constructor since the program won't even run).

    ReplyDelete