Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Placement forms of the operator delete functions

In his new book TC++PL4, Stroustrup casts a slightly different light on a once usual practice regarding user-controlled memory allocation and placement new—or, more specifically, regarding the enigmatical "placement delete." In the book's sect. 11.2.4, Stroustrup writes:

The "placement delete" operators do nothing except possibly inform a garbage collector that the deleted pointer is no longer safely derived.

This implies that sound programming practice will follow an explicit call to a destructor by a call to placement delete.

Fair enough. However, is there no better syntax to call placement delete than the obscure

::operator delete(p);

The reason I ask is that Stroustrup's sect. 11.2.4 mentions no such odd syntax. Indeed, Stroustrup does not dwell on the matter; he mentions no syntax at all. I vaguely dislike the look of ::operator, which interjects the matter of namespace resolution into something that properly has nothing especially to do with namespaces. Does no more elegant syntax exist?

For reference, here is Stroustrup's quote in fuller context:

By default, operator new creates its object on the free store. What if we wanted the object allocated elsewhere?... We can place objects anywhere by providing an allocator function with extra arguments and then supplying such extra arguments when using new:

void* operator new(size_t, void* p) { return p; }

void buf = reinterpret_cast<void*>(0xF00F);
X* p2 = new(buf) X;

Because of this usage, the new(buf) X syntax for supplying extra arguments to operator new() is known as the placement syntax. Note that every operator new() takes a size as its first argument and that the size of the object allocated is implicitly supplied. The operator new() used by the new operator is chosen by the usual argument-matching rules; every operator new() has a size_t as its first argument.

The "placement" operator new() is the simplest such allocator. It is defined in the standard header <new>:

void* operator new (size_t, void* p) noexcept;
void* operator new[](size_t, void* p) noexcept;

void* operator delete (void* p, void*) noexcept; // if (p) make *p invalid
void* operator delete[](void* p, void*) noexcept;

The "placement delete" operators do nothing except possibly inform a garbage collector that the deleted pointer is no longer safely derived.

Stroustrup then continues to discuss the use of placement new with arenas. He does not seem to mention placement delete again.

like image 913
thb Avatar asked Jun 30 '13 15:06

thb


People also ask

Is there a placement delete?

Placement deleteIt is not possible to call any placement operator delete function using a delete expression. The placement delete functions are called from placement new expressions. In particular, they are called if the constructor of the object throws an exception.

What is the delete operator?

The delete operator removes a given property from an object. On successful deletion, it will return true , else false will be returned.

What is delete function C++?

When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.

What are new and delete operators in C++?

These operators allocate memory for objects from a pool called the free store (also known as the heap). The new operator calls the special function operator new , and the delete operator calls the special function operator delete .


1 Answers

If you don't want to use ::, you don't really have to. In fact, you generally shouldn't (don't want to).

You can provide replacements for ::operator new and ::operator delete (and the array variants, though you should never use them).

You can also, however, overload operator new and operator delete for a class (and yes, again, you can do the array variants, but still shouldn't ever use them).

Using something like void *x = ::operator new(some_size); forces the allocation to go directly to the global operator new instead of using a class specific one (if it exists). Generally, of course, you want to use the class specific one if it exists (and the global one if it doesn't). That's exactly what you get from using void *x = operator new(some_size); (i.e., no scope resolution operator).

As always, you need to ensure that your news and deletes match, so you should only use ::operator delete to delete the memory when/if you used ::operator new to allocate it. Most of the time you shouldn't use :: on either one.

The primary exception to that is when/if you're actually writing an operator new and operator delete for some class. These will typically call ::operator new to get a big chunk of memory, then divvy that up into object-sized pieces. To allocate that big chunk of memory, it typically (always?) has to explicitly specify ::operator new because otherwise it would end up calling itself to allocate it. Obviously, if it specifies ::operator new when it allocates the data, it also needs to specify ::operator delete to match.

like image 167
Jerry Coffin Avatar answered Sep 20 '22 00:09

Jerry Coffin