The new operator in C++ |
Written by Eli Bendersky | ||||
Tuesday, 29 March 2011 | ||||
Page 1 of 3
At first glance, dynamic allocation of objects in C++ is simple: new to allocate, delete to deallocate, and you’re done. However, under the hood, the issue is much more complex and allows a considerable level of customization. This may not be important for simple applications, but is essential when you need better control of memory in your code, whether by writing a custom allocator, some kind of advanced memory management scheme or a specialized garbage collector. This article doesn’t aim to be a comprehensive manual, but a brief overview of the various ways memory can be allocated in C++. It’s not basic, and assumes a good familiarity with the language. Raw operator newLet’s start with the raw operator new. Consider this code, which allocates space for 5 integers and returns a pointer to it: int* v = static_cast<int*> Notice that I wrote :: before operator new explicitly although it's not strictly required in this case. I regard this is a good practice, especially when used inside overloaded operator new methods to avoid ambiguity. When called like this, operator new acts as a raw memory allocator, similar to malloc. The above line is conceptually equivalent to: int* v = static_cast<int*> Freeing memory allocated with the raw operator new is done with the raw operator delete: ::operator delete(v); Would you ever use the raw new and delete functions? Yes, in some rare cases, as I’ll demonstrate later in the article. Why use them instead of the old and trusted malloc and free? One good reason is that you want to keep your code wholly in the C++ domain. Mixing new with free (or malloc with delete) is a big NO NO. Another reason is that you can overload or override these functions if you need to. Here’s an example: void* operator new(size_t sz) In general, keep in mind that the global operator new function is called when the new operator is used to allocate objects of built-in types, objects of class type that do not contain user-defined operator new functions, and arrays of any type. When the new operator is used to allocate objects of a class type where an operator new is defined, that class’s operator new is called. And this brings us to classes with operator new. Class-specific operator newPeople sometimes wonder what’s the difference between "operator new" and the "new operator". The former refers to either an overloaded operator new, global or class-specific, or the raw operator new function presented earlier. The latter refers to the built-in C++ new operator you usually employ to allocate memory, as in: Car* mycar = new Car; C++ supports operator overloading, and one of the operators it lets us overload is new. Here’s an example: class Base { public: void* operator new(size_t sz) { cerr << "new " << sz << " bytes\n"; return ::operator new(sz); } This prints: new 4 bytes delete new 56 bytes delete The overloaded operator new and operator delete in the base class are also inherited by derived classes. As you can see, the operator new method gets the correct size to allocate in both cases. Note also that to actually allocate the memory, it uses ::operator new, the raw operator new described in the previous section. The double-colon in the call is essential in this case to avoid infinite recursion (without it the method would just call itself). Why would you overload operator new for a class? There are many reasons.
|
||||
Last Updated ( Tuesday, 29 March 2011 ) |