Placement syntax: Difference between revisions

Content deleted Content added
Citation bot (talk | contribs)
Added publisher. | Use this bot. Report bugs. | Suggested by Abductive | Category:Vague or ambiguous time from April 2025 | #UCB_Category 151/398
No edit summary
Line 18:
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 />
<syntaxhighlight lang="cpp">
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);
</syntaxhighlight>
 
The Standard C++ library provides two placement overloads each for these functions. Their declarations are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b />
<syntaxhighlight lang="cpp">
void* operator new(std::size_t, const std::nothrow_t&) throw()noexcept;
void* operator new(std::size_t, void*) throw()noexcept;
void* operator new[](std::size_t, const std::nothrow_t&) throw()noexcept;
void* operator new[](std::size_t, void*) throw()noexcept;
</syntaxhighlight>
 
Line 34:
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 />
<syntaxhighlight lang="cpp">
void operator delete(void*) throw()noexcept;
void operator delete[](void*) throw()noexcept;
</syntaxhighlight>
 
The Standard C++ library provides two placement overloads each for these functions. Their declarations are:<ref name=Vermeir2001 /><ref name=Stroustrup1997b />
<syntaxhighlight lang="cpp">
void operator delete(void*, const std::nothrow_t&) throw()noexcept;
void operator delete(void*, void*) throw()noexcept;
void operator delete[](void*, const std::nothrow_t&) throw()noexcept;
void operator delete[](void*, void*) throw()noexcept;
</syntaxhighlight>
 
Line 56:
The placement overloads of <code>operator new</code> and <code>operator delete</code> that employ an additional <syntaxhighlight lang="cpp" inline>void *</syntaxhighlight> 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 />
<syntaxhighlight lang="cpp">
void* operator new(std::size_t, void* p) throw()noexcept { return p; }
void* operator new[](std::size_t, void* p) throw()noexcept { return p; }
void operator delete(void*, void*) throw()noexcept { }
void operator delete[](void*, void*) throw()noexcept { }
</syntaxhighlight>
 
Line 83:
This operator is implemented as:
<syntaxhighlight lang="cpp">
void* operator new(std::size_t count, void* here) noexcept { return here; }
void* operator new[](std::size_t count, void* here) noexcept { return here; }
</syntaxhighlight>
 
Line 90:
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 <syntaxhighlight lang="cpp" inline>NULL</syntaxhighlight> 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> (or import the <code>std</code> module) 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 <syntaxhighlight lang="cpp" inline>const std::nothrow_t &</syntaxhighlight> as their second parameter. For example:<ref name=Anderson1998a />
<syntaxhighlight lang="cpp">
import std;
#include <new>
 
struct T {};
Line 109:
 
=== 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 />
<syntaxhighlight lang="cpp">
import std;
#include <cstdlib>
 
class A {
public:
Line 186 ⟶ 187:
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 />
<syntaxhighlight lang="cpp">
import std;
#include <new>
#include <cstdlib>
 
class NewErrorAlloationError {
public:
NewErrorAlloationError(const char* file, int line) { /* ... */ }
/* ... */
} ;
 
void* operator new(std::size_t size, const char* file, int line) {
void *
operator new(std::size_t size, const char* file, int line)
{
if (void* p = ::operator new(size, std::nothrow))
return p;
throw NewErrorAlloationError(file, line);
}
</syntaxhighlight>
Line 211 ⟶ 209:
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 />
<syntaxhighlight lang="cpp">
import std;
#include <cstdlib>
#include <iostream>
 
struct A {};
Line 222 ⟶ 219:
};
 
void * operator new(std::size_t, const A&) {
std::cout << println("Placement new called." << std::endl);
}
 
void operator delete(void*, const A&) {
std::cout << println("Placement delete called." << std::endl);
}
 
Line 235 ⟶ 232:
T* p = new(a) T;
} catch (E exp) {
std::cout << println("Exception caught." << std::endl);
}
return 0;