Placement syntax: Difference between revisions

Content deleted Content added
BattyBot (talk | contribs)
m References: fixed citation template(s) to remove page from Category:CS1 maint: Extra text & general fixes using AWB (11334)
WP:FIX + general fixes, typo(s) fixed: Therefore → Therefore, using AWB
Line 1:
In the [[C++]] [[programming language]], '''placement [[Syntax (programming languages)|syntax]]''' allows programmers to explicitly specify the [[memory management]] of individual objects&nbsp;— i.e. their "placement" in [[memory (computing)|memory]]. Normally, when an object is created dynamically, an allocation function is invoked in such a way that it will both allocate memory for the object, and [[Constructor (object-oriented programming)|initialize]] the object within the newly allocated memory.<!--5.3.5--> The placement syntax allows the programmer to supply additional arguments to the allocation function. A common use is to supply a [[pointer (computer programming)|pointer]] to a suitable region of storage where the object can be initialized, thus separating memory allocation from object construction.{{Citation needed|date=October 2010}}
 
The "placement" versions of the <code>[[new (C++)|new]]</code> and <code>[[delete (C++)|delete]]</code> operators and functions are known as placement <code>new</code> and placement <code>delete</code>.<ref name=McCluskey2000 /> A <code>new</code> ''expression'', placement or otherwise, calls a <code>new</code> ''function'', also known as an allocator function, whose name is <code>operator new</code>. Similarly, a <code>delete</code> ''expression'' calls a <code>delete</code> ''function'', also known as a deallocator function, whose name is <code>operator delete</code>.<ref name=Lischner2003 /><ref name=Lippman1997 />
 
Any <code>new</code> expression that uses the placement syntax is a placement <code>new</code> expression, and any <code>operator new</code> or <code>operator delete</code> function that takes more than the mandatory first parameter (<source lang="cpp" enclose=none>std::size_t</source> and <source lang="cpp" enclose=none>void *</source>, respectively) is a placement new or placement delete function.<ref name=Meyers1998 />
Line 10:
== Expressions ==
The Standard C++ syntax for a non-placement <code>new</code> expression is<ref name=Lischner2003 />
: <code>new ''new-type-id'' ( ''optional-initializer-expression-list'' )</code>
 
The placement syntax adds an expression list immediately after the <code>new</code> keyword. This expression list is the placement. It can contain any number of expressions.<ref name=Lischner2003 /><ref name=Lippman1997 /><ref name=Loudon2003 />
: <code>new ( ''expression-list'' ) ''new-type-id'' ( ''optional-initializer-expression-list'' )</code>
 
There is no placement delete expression.<ref name=SolterKleper2005 />
 
== Functions ==
The placement new functions are overloads of the non-placement new functions. The declaration of the non-placement new functions, for non-array and array <code>new</code> expressions respectively, are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
void * operator new (std::size_t) throw(std::bad_alloc);
void * operator new[] (std::size_t) throw(std::bad_alloc);
</source>
 
The Standard C++ library provides two placement overloads each for these functions. Their declarations are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
void * operator new (std::size_t, const std::nothrow_t &) throw();
void * operator new (std::size_t, void *) throw();
Line 30:
</source>
 
In all of the overloads, the first parameter to the <code>operator new</code> function is of type <source lang="cpp" enclose=none>std::size_t</source>, which when the function is called will be passed as an argument specifying the amount of memory, in bytes, to allocate. All of the functions must return type <source lang="cpp" enclose=none>void *</source>, which is a [[pointer (computer programming)|pointer]] to the storage that the function allocates.<ref name=Lischner2003 />
 
There are also placement delete functions. They are overloaded versions of the non-placement delete functions. The non-placement delete functions are declared as:<ref name=Vermeir2001 /><ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
void operator delete (void *) throw();
void operator delete[] (void *) throw();
</source>
 
The Standard C++ library provides two placement overloads each for these functions. Their declarations are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
void operator delete (void *, const std::nothrow_t &) throw();
void operator delete (void *, void *) throw();
Line 52:
 
=== Default placement ===
The placement overloads of <code>operator new</code> and <code>operator delete</code> that employ an additional <source lang="cpp" enclose=none>void *</source> parameter are used for default placement, also known as ''pointer placement''. Their definitions by the Standard C++ library, which it is not permitted for a C++ program to replace or override, are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b /><ref name=Anderson1998a /><source lang="cpp" enclose=div>
void * operator new (std::size_t, void * p) throw() { return p ; }
void * operator new[] (std::size_t, void * p) throw() { return p ; }
Line 67:
Other uses, however, include calling a constructor directly, something which the C++ language does not otherwise permit.<ref name=Lippman1997 />
 
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=SolterKleper2005 /><ref name=SeedCooper2001 />
: <source lang="cpp" enclose=div>
p->~T() ;
</source>
Line 77:
* You want to separate memory allocation from construction e.g. in implementing a std::vector<> (see std::vector<>::reserve).
 
The basic problem is that the constructor is a peculiar function; when it starts off, there is no object, only raw memory. And by the time it finishes, you have a fully initialized object. Therefore, i) The constructor cannot be called on an object ii) However, it needs to access (and initialize) non-static members. This makes calling the constructor directly an error. The solution is the placement form of operator new.
 
This operator is implemented as:<source lang="cpp" enclose=div>
Line 100:
 
=== 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=Lippman1997 /><ref name=Meyers1998 /><ref name=Loudon2003 />
 
Programmers who wish to do this in their programs must include the Standard C++ library header <code>&lt;new&gt;</code> in the source code. This header declares the global <code>std::nothrow</code> object, which is of type <code>std::nothrow_t</code> (also declared in the header), which is used to call the overloaded new functions that are declared as taking <source lang="cpp" enclose=none>const std::nothrow_t &</source> as their second parameter. For example:<ref name=Anderson1998a /><source lang="cpp" enclose=div>
#include <new>
 
Line 121:
 
=== Custom allocators ===
Placement syntax is also employed for custom [[allocator (C++)|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=Vermeir2001 /><ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
#include <cstdlib>
class A {
Line 149:
</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=SolterKleper2005 /><ref name=Vermeir2001 /><ref name=Stroustrup1997b />
 
The former would resemble:<ref name=Stroustrup1997b /><source lang="cpp" enclose=div>
Line 174:
</source>
 
A common error is to attempt to use a delete expression to delete the object. This results in the wrong <code>operator delete</code> function being called. Dewhurst recommends two strategies for avoiding this error. The first is to ensure that any custom allocators rely upon the Standard C++ library's global, non-placement, <code>operator new</code>, and are thus nothing more than simple wrappers around the C++ library's memory management. The second is to create new and delete functions for individual classes, and customize memory management via class function members rather than by using the placement syntax.<ref name=Dewhurst2003 />
 
=== 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=Anderson1998a /><ref name=Yongwei2007 /><source lang="cpp" enclose=div>
#if defined(DEBUG_NEW)
void * operator new (std::size_t size, const char* file, int line);
Line 193:
</source>
 
The custom-written placement new functions would then handle using the supplied file and line number information in the event of an exception. For example:<ref name=Anderson1998a /><ref name=Yongwei2007 /><source lang="cpp" enclose=div>
#include <new>
#include <cstdlib>
Line 213:
 
== Placement delete ==
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=SolterKleper2005 /><ref name=Anderson1998b />
 
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=Lischner2003 /><ref name=Meyers1998 /><ref name=SolterKleper2005 /><ref name=Anderson1998b />
 
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=Lischner2003 /><ref name=SolterKleper2005 /><ref name=Anderson1998b /><source lang="cpp" enclose=div>
#include <cstdlib>
#include <iostream>
Line 245:
</source>
 
This is why the ''pointer placement'' delete functions are defined as no-operations by the Standard C++ library. Since the pointer placement new functions do not allocate any storage, there is no storage to be deallocated in the event of the object's constructor throwing an exception.<ref name=SolterKleper2005 />
 
If no matching placement delete function exists, no deallocation function is called in the event of an exception being thrown by a constructor within a placement <code>new</code> expression. There are also some (older) C++ implementations that do not support placement delete (which, like the exception-throwing allocator functions, were an addition made to C++ when it was standardized) at all. In both such situations, an exception being thrown by a constructor when allocating using a custom allocator will result in a memory leak. (In the case of the older C++ implementations, a memory leak will also occur with ''non-''placement <code>new</code> expressions.)<ref name=Meyers1998 /><ref name=Anderson1998b />
 
== Notes ==
{{reflist|3|refs=
<ref name=Anderson1998a>{{harvnb|Anderson|1998a|pp=345–356}}</ref>
<ref name=Anderson1998b>{{harvnb|Anderson|1998b|pp=631–632}}</ref>
Line 271:
== References ==
{{refbegin|1}}
* {{cite book|ref=harv|title=Navigating C++ and Object-oriented Design|first=Gail|last=Anderson|chapter=Object Storage Management|publisher=Prentice Hall|year=1998a|isbn=9780135327487}}
* {{cite book|ref=harv|title=Navigating C++ and Object-oriented Design|first=Gail|last=Anderson|chapter=Exception Handling|publisher=Prentice Hall|year=1998b|isbn=9780135327487}}
* {{cite web|ref=harv|url=http://www.desy.de/user/projects/C++/g++faq/placement_new_syntax.html|title=3.4. g++ won't accept the placement new syntax.|date=1997-05-12|first=Joe|last=Buck|work=Frequently asked questions about the GNU C++ compiler|accessdate=2008-11-26}}
* {{cite book|ref=harv|title=C++ Gotchas|first=Stephen C.|last=Dewhurst|chapter=Gotcha #62: Replacing Global New and Delete|chapterurl=http://informit.com/articles/article.aspx?p=30642&seqNum=3|publisher=[[Addison-Wesley]]|year=2003|isbn=978-0-321-12518-7}}
* {{cite book|ref=harv|title=C++ in a Nutshell|first=Ray|last=Lischner|publisher=O'Reilly|year=2003|isbn=9780596002985}}
* {{cite book|ref=harv|title=C++ Gems|first=Stanley B.|last=Lippman|authorlink= Stanley B. Lippman |publisher=Cambridge University Press|year=1997|isbn=9780135705810}}
* {{cite book|ref=harv|title=C++ Pocket Reference|first=Kyle|last=Loudon|publisher=O'Reilly|year=2003 |isbn=9780596004965}}
* {{cite web|ref=CITEREFMcCluskey2000|url=http://glenmccl.com/nd_cmp.htm|title=Placement New/Delete|publisher=Glen McCluskey &amp; Associates LLC|work=C++ Language and Library|date=2000-06-26|accessdate=2008-11-26}}
* {{cite news|ref=harv|date=1998-04-01|first=Scott|last=Meyers|title=Placement new and placement delete|url=http://ddj.com/showArticle.jhtml?documentID=cuj9804meyers&pgno=2|work=[[Dr. Dobb's Journal]]|publisher=United Business Media LLC}}
* {{cite book|ref=harv|title=An Introduction to Object-oriented Programming in C++|first1=Graham M.|last1=Seed|first2=Barry J.|last2=Cooper|publisher=Springer|year=2001|isbn=1-85233-450-9|edition=Second}}
* {{cite book|ref=harv|title=Professional C++|first1=Nicholas|last1=Solter|first2=Scott|last2=Kleper|publisher=Wiley|year=2005|isbn=9780764574849}}
* {{cite book|ref=harv|title=The C++ Programming Language|edition=2nd|first=Bjarne|last=Stroustrup|authorlink=Bjarne Stroustrup|isbn=978-0-201-53992-9|date=July 1991}}
* {{cite book|ref=harv|last=Stroustrup|first=Bjarne|authorlink=Bjarne Stroustrup|title=Design and Evolution of C++|publisher=[[Addison-Wesley]]|isbn=978-0-201-54330-8|year=1994|chapter=Memory Management}}
* {{cite book|ref=harv|last=Stroustrup|first=Bjarne|authorlink=Bjarne Stroustrup|title=The C++ Programming Language|publisher=[[Addison-Wesley]]|edition=3rd|isbn=978-0-201-88954-3|year=1997}}
* {{cite book|ref=harv|title=Multi-paradigm Programming Using C++|first=Dirk|last=Vermeir|publisher=Springer|year=2001|isbn=9781852334833}}
* {{cite web|ref=harv|title=A Cross-Platform Memory Leak Detector|date=2007-12-31|first=Wu|last=Yongwei|accessdate=2008-11-26|work=Wu Yongwei's Programming Page|url=http://wyw.dcweb.cn/leakage.htm}}
{{refend}}