Placement syntax: Difference between revisions

Content deleted Content added
Copyedited and corrected.
Expanded further.
Line 70:
Other uses, however, include calling a constructor directly, something which the C++ language does not otherwise permit.<ref name=Lippman1 />
 
The C++ language does allow a program to call a [[destructor (computer science)|destructor]] directly, and, since it is not possible to destroy the object using a <code>delete</code> expression, that is how one destroys an object that was constructed via a pointer placement new expression. For example:<ref name=SeedCooper>{{cite book|title=An Introduction to Object-oriented Programming in C++|author=Graham M. Seed and Barry J. Cooper|pages=435&ndash;436|publisher=Springer|date=2001|isbn=1852334509|edition=Second Edition}}</ref><ref name=SolterKleper />
:<source lang="cpp" enclose=div>
p->~T() ;
</source>
=== Preventing exceptions ===
Normally, the (non-placement) new functions throw an exception, of type <code>std::bad_alloc</code>, if they encounter an error, such as exhaustion of all available memory. This was not how the functions were defined by Stroustrup's ''Annotated C++ Reference Manual'', but was a change made by the standardization committee when the C++ language was standardized. The original behaviour of the functions, which was to return a <source lang="cpp" enclose=none>NULL</source> pointer when an error occurred, is accessible via placement syntax.<ref name=Lippman1 />
Line 93 ⟶ 97:
 
=== Custom allocators ===
Placement syntax is also employed for custom allocators. This does not use any of the allocator and deallocator functions from the Standard C++ library header <code>&lt;new&gt;</code>, but requires that programmers write their own allocation and deallocation functions, overloaded for user-defined types. For example, one could define a memory management class as follows:<ref name=TCPPPL /><ref name=Vermeir1 />
{{sect-stub}}
:<source lang="cpp" enclose=div>
#include <cstdlib>
class A {
void * allocate ( size_t ) ;
void deallocate ( void * ) ;
} ;
</source>
 
And define custom placement allocation and deallocation functions as follows:<ref name=TCPPPL /><ref name=Vermeir1 />
:<source lang="cpp" enclose=div>
void *
operator new (size_t size, A & arena)
{
return arena.alloc(size) ;
}
void
operator delete (void * p, A & arena)
{
arena.deallocate(p) ;
}
</source>
 
The program would employ the placement syntax to allocate objects using different instances of the <code>A</code> class as follows:<ref name=TCPPPL /><ref name=Vermeir1 />
:<source lang="cpp" enclose=div>
A first_arena, second_arena ;
T * p1 = new (first_arena) T ;
T * p2 = new (second_arena) T ;
</source>
 
Destroying an object whose storage is allocated in such a fashion requires some care. Because there is no placement delete expression, one cannot use it to invoke the custom deallocator. One must either write a destruction function that invokes the custom deallocator, or call the placement delete function directly, as a function call.<ref name=SolterKleper /><ref name=TCPPPL /><ref name=Vermeir1 />
 
The former would resemble:<ref name=TCPPPL />
:<source lang="cpp" enclose=div>
void
destroy (T * p, A & arena)
{
p->~T() ; // First invoke the destructor explicitly.
arena.deallocate(p) ; // Then call the deallocator function directly.
}
</source>
which would be invoked from a program as:
:<source lang="cpp" enclose=div>
A arena ;
T * p = new (arena) T ;
/* ... */
destroy(p, arena) ;
</source>
 
 
The latter would involve simply writing the function call into the program:<ref name=Vermeir1 />
:<source lang="cpp" enclose=div>
A arena ;
T * p = new (arena) T ;
/* ... */
operator delete(p, arena) ;
</source>
 
=== Debugging ===
Placement new can also be used as a simple debugging tool, to enable programs to print the filename and line number of the source code where a memory allocation has failed. This does not require the inclusion of the Standard C++ library header <code>&lt;new&gt;</code>, but does require the inclusion of a header that declares four placement functions and a macro replacement for the <code>new</code> keyword that is used in new expressions. For example, such a header would contain:<ref name=Anderson1 /><ref name=Yongwei1>{{cite web|title=A Cross-Platform Memory Leak Detector|date=[[2007-12-31]]|author=Wu Yongwei|accessdate=[[2008-11-26]]|work=Wu Yongwei's Programming Page|url=http://wyw.dcweb.cn/leakage.htm}}</ref>
Line 135 ⟶ 196:
As noted above, there is no placement delete expression. It is not possible to call ''any'' placement <code>operator delete</code> function using a <code>delete</code> expression.<ref name=SolterKleper />
 
The placement delete functions are called from placement <code>new</code> expressions. In particular, they are called if the [[constructor (computer science)|constructor]] of the object throws an exception. In such a circumstance, in order to ensure that the program does not incur a memory leak, the placement delete functions are called. A placement new expression first calls the placement <code>operator new</code> function, then calls the constructor of the object upon the raw storage returned from the allocator function. If the constructor throws an exception, it is necessary to deallocate that storage before propagating the exception back to the code that executed the placement new expression, and that is the purpose of the placement delete functions.<ref name=SolterKleper /><ref name=Lischner1 />
 
The placement delete function that is called matches the placement new function that was invoked by the placement new expression. So, for example, if the following code is executed, the placement delete function that is called will be <code>operator delete(void *, const A &)</code>:<ref name=SolterKleper /><ref name=Lischner1 />
:<source lang="cpp" enclose=div>
#include <cstdlib>