{"id":4853,"date":"2008-08-28T17:51:00","date_gmt":"2008-08-28T17:51:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2008\/08\/28\/the-mallocator\/"},"modified":"2019-02-18T18:54:01","modified_gmt":"2019-02-18T18:54:01","slug":"the-mallocator","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/the-mallocator\/","title":{"rendered":"The Mallocator"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"3\">A common question from programmers who have an intermediate amount of experience with using the STL is, &#8220;How do I write an STL allocator?&#8221;.&nbsp; Writing an STL allocator is not especially difficult &#8211; only two member functions are interesting, allocate() and deallocate().&nbsp; However, STL allocators must satisfy a number of other requirements (given by section 20.1.5 of the International Standard for C++, ISO\/IEC 14882:2003), and the code to do so takes roughly 80 editor lines.&nbsp; Figuring out the code from the requirements can be overwhelming, but once you see the code, it&#8217;s easy.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Verdana\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"3\">One thing some programmers try is to derive from std::allocator.&nbsp; I recommend against this; it&#8217;s more trouble than it&#8217;s worth.&nbsp; Looking at std::allocator&#8217;s implementation is also painful.<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Verdana\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Verdana\" size=\"3\">Therefore, I&#8217;ve written an example STL allocator, whose purpose in life is to wrap malloc() and free(), which I&#8217;ve imaginatively called Mallocator.&nbsp; I&#8217;ve carefully implemented all of the integer overflow checks and so forth that would be required in real production code.&nbsp; And I&#8217;ve exhaustively commented which parts of Mallocator are boilerplate (common to all, virtually all, or all stateless allocators), and which parts you would have to customize.&nbsp; Hopefully, this should demystify the implementation of STL allocators:<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Verdana\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Verdana\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">C:Temp&gt;type mallocator.cpp<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">\/\/ The following headers are required for all allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;stddef.h&gt;&nbsp; \/\/ Required for size_t and ptrdiff_t and NULL<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;new&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Required for placement new and std::bad_alloc<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;stdexcept&gt; \/\/ Required for std::length_error<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">\/\/ The following headers contain stuff that Mallocator uses.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;stdlib.h&gt;&nbsp; \/\/ For malloc() and free()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;iostream&gt;&nbsp; \/\/ For std::cout<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;ostream&gt;&nbsp;&nbsp; \/\/ For std::endl<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">\/\/ The following headers contain stuff that main() uses.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#include &lt;list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ For std::list<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">template &lt;typename T&gt; class Mallocator {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">public:<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ The following will be the same for virtually all allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef T * pointer;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef const T * const_pointer;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef T&amp; reference;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef const T&amp; const_reference;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef T value_type;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef size_t size_type;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; typedef ptrdiff_t difference_type;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; T * address(T&amp; r) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return &amp;r;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; const T * address(const T&amp; s) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &amp;s;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; size_t max_size() const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ The following has been carefully written to be independent of<\/p>\n<p><\/font><\/s><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ the definition of size_t and to avoid signed\/unsigned warnings.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (static_cast&lt;size_t&gt;(0) &#8211; static_cast&lt;size_t&gt;(1)) \/ sizeof(T);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ The following must be the same for all allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; template &lt;typename U&gt; struct rebind {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; typedef Mallocator&lt;U&gt; other;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; };<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; bool operator!=(const Mallocator&amp; other) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return !(*this == other);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; void construct(T * const p, const T&amp; t) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void * const pv = static_cast&lt;void *&gt;(p);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new (pv) T(t);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; void destroy(T * const p) const; \/\/ Defined below.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ Returns true if and only if storage allocated from *this<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ can be deallocated from other, and vice versa.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ Always returns true for stateless allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; bool operator==(const Mallocator&amp; other) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;return true;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ Default constructor, copy constructor, rebinding constructor, and destructor.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ Empty for stateless allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; Mallocator() { }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; Mallocator(const Mallocator&amp;) { }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; template &lt;typename U&gt; Mallocator(const Mallocator&lt;U&gt;&amp;) { }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; ~Mallocator() { }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ The following will be different for each allocator.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; T * allocate(const size_t n) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Mallocator prints a diagnostic message to demonstrate<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ what it&#8217;s doing. Real allocators won&#8217;t do this.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &#8220;Allocating &#8221; &lt;&lt; n &lt;&lt; (n == 1 ? &#8221; object&#8221; : &#8220;objects&#8221;)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&lt; &#8221; of size &#8221; &lt;&lt; sizeof(T) &lt;&lt; &#8220;.&#8221; &lt;&lt; std::endl;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ The return value of allocate(0) is unspecified.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\/\/ Mallocator returns NULL in order to avoid depending<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ on malloc(0)&#8217;s implementation-defined behavior<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ (the implementation can define malloc(0) to return NULL,<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ in which case the bad_alloc check below would fire).<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;\/\/ All allocators can return NULL in this case.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (n == 0) {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ All allocators should contain an integer overflow check.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ The Standardization Committee recommends that std::length_error<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;\/\/ be thrown in the case of integer overflow.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (n &gt; max_size()) {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw std::length_error(&#8220;Mallocator&lt;T&gt;::allocate() &#8211; Integer overflow.&#8221;);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Mallocator wraps malloc().<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void * const pv = malloc(n * sizeof(T));<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Allocators should throw std::bad_alloc in the case of memory allocation failure.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pv == NULL) {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw std::bad_alloc();<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return static_cast&lt;T *&gt;(pv);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; void deallocate(T * const p, const size_t n) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Mallocator prints a diagnostic message to demonstrate<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ what it&#8217;s doing. Real allocators won&#8217;t do this.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; std::cout &lt;&lt; &#8220;Deallocating &#8221; &lt;&lt; n &lt;&lt; (n == 1 ? &#8221; object&#8221; : &#8220;objects&#8221;)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;&lt; &#8221; of size &#8221; &lt;&lt; sizeof(T) &lt;&lt; &#8220;.&#8221; &lt;&lt; std::endl;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \/\/ Mallocator wraps free().<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free(p);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ The following will be the same for all allocators that ignore hints.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; template &lt;typename U&gt; T * allocate(const size_t n, const U * \/* const\nhint *\/) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return allocate(n);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; }<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ Allocators are not required to be assignable, so<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ all allocators should have a private unimplemented<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ assignment operator. Note that this will trigger the<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ off-by-default (enabled under \/Wall) warning C4626<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ &#8220;assignment operator could not be generated because a<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ base class assignment operator is inaccessible&#8221; within<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; \/\/ the STL headers, but that warning is useless.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">private:<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; Mallocator&amp; operator=(const Mallocator&amp;);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">};<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">\/\/ A compiler bug causes it to believe that p-&gt;~T() doesn&#8217;t reference p.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#ifdef _MSC_VER<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; #pragma warning(push)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; #pragma warning(disable: 4100) \/\/ unreferenced formal parameter<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#endif<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">\/\/ The definition of destroy() must be the same for all allocators.<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">template &lt;typename T&gt; void Mallocator&lt;T&gt;::destroy(T * const p) const {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; p-&gt;~T();<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#ifdef _MSC_VER<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; #pragma warning(pop)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">#endif<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">int main() {<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; using namespace std;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; cout &lt;&lt; &#8220;Constructing l:&#8221; &lt;&lt; endl;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; list&lt;int, Mallocator&lt;int&gt; &gt; l;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl &lt;&lt; &#8220;l.push_back(1729):&#8221; &lt;&lt; endl;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; l.push_back(1729);<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; cout &lt;&lt; endl &lt;&lt; &#8220;l.push_back(2161):&#8221; &lt;&lt; endl;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\">&nbsp;&nbsp;&nbsp; l.push_ba<\/font><\/span><\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A common question from programmers who have an intermediate amount of experience with using the STL is, &#8220;How do I write an STL allocator?&#8221;.&nbsp; Writing an STL allocator is not especially difficult &#8211; only two member functions are interesting, allocate() and deallocate().&nbsp; However, STL allocators must satisfy a number of other requirements (given by section [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[3],"class_list":["post-4853","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","tag-dev"],"acf":[],"blog_post_summary":"<p>A common question from programmers who have an intermediate amount of experience with using the STL is, &#8220;How do I write an STL allocator?&#8221;.&nbsp; Writing an STL allocator is not especially difficult &#8211; only two member functions are interesting, allocate() and deallocate().&nbsp; However, STL allocators must satisfy a number of other requirements (given by section [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4853","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=4853"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4853\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=4853"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=4853"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=4853"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}