The principle of http://blog.csdn.net/kevin_qing/article/details/608891 here
The previous Code cannot be found. Rewrite it once.
Added some simple error detection code. Helps debug memory problems.
Preliminary code, not carefully checked. Please leave a message if any bug exists.
// Type and macro # include <default. h> // debug information constbooldebugqmem = 1; structqmemdebuginfo {uint32_tmask; uint32_tsize; byteguard [128-8] ;}; template <bool flag, typename t, typename u> struct typeselectt {private: Template <bool> struct in {typedef t result ;}; template <> struct in <false> {typedef U result ;}; public: typedef typename in <flag>: Result result;}; // calculate Ln (X)/ln (Y) and convert it to an integer template <uint64_t X, uint 64_t y> struct logt {protected: Template <uint64_t x1> struct imp {Enum {next = (X1 + Y-1)/y ,}; enum {result = 1 + imP <next >:: result };}; template <> struct imP <1 >{ Enum {result = 0 };}; public: enum {result = imP <X >:: result };}; // x ^ ytemplate <uint64_t X, uint64_t y> struct powert {protected: template <uint64_t Y1> struct imp {Enum {next = y1-1}; Enum {result = x * imP <next >:: result };}; template <> struct imP <0> {Enum {Result = 1 };}; public: Enum {result = imP <y >:: result };}; // cache table, template <uint64_t index> struct cachecount {// table <> is not 0, 1, 2, and 3. Therefore, the compilation of <16B objects is not allowed, so the debugging information cannot be accommodated because the space is too small. Template <uint64_t> structtable; Template <> struct table <4 >{ Enum {result = 4096 };}; // 16B-> 64 ktemplate <> struct table <5 >{ Enum {result = 4096 };}; // 32B-> 128 ktemplate <> struct table <6 >{ Enum {result = 4096 };}; // 64b-> 256 ktemplate <> struct table <7 >{ Enum {result = 4096 };}; // 128b-> 512 ktemplate <> struct table <8 >{ Enum {result = 2048 };}; // 256b-> 512 ktemplate <> struct table <9 >{ Enum {result = 2048 };}; // 512b-> 1mt Emplate <> struct table <10 >{ Enum {result = 2048 };}; // 1 K-> 2 mtemplate <> struct table <11 >{ Enum {result = 2048 };}; // 2 k-> 4 mtemplate <> struct table <12 >{ Enum {result = 1024 };}; // 4 K-> 4 mtemplate <> struct table <13 >{ Enum {result = 1024 };}; // 8 K-> 8 mtemplate <> struct table <14 >{ Enum {result = 1024 };}; // 16 K-> 16 m // Add template for more use <> struct table <20 >{ Enum {result = 4 };}; // 1 m-> 4 mstructmincache {Enum {result = 2 };}; Enum {result = typeselectt <index <20, table <logt <index, 2 >:: result>, mincache >:: result :: result };}; // linked list, for available space recycling structqmemlink {qmemlink * Next;}; classqmemtest; byte * qalloc (size_t s) {returnnew byte [s];} template <size_t size> class qfixallocator {friendclassqmemtest; bytes; uint64_tallocbytes; uint64_tpoolbytes; qmemlink * mempool; Enum {sizefix = powert <2, logt <size, 2 >:: result}; Enum {caches = cacheco Unt <sizefix >:: result}; protected: qfixallocator () {usagebytes = 0; allocbytes = 0; poolbytes = 0; mempool = NULL;} public: void * alloc (size_t s) {assert (S <= sizefix); // avoid new [] Call to the wrong Allocator, host class should use a separate version of new [] () instead of calling New () qmemlink * r by default; If (mempool) {r = mempool; mempool = mempool-> next; poolbytes-= sizefix; usagebytes + = s; returnr;} byte * P = qalloc (sizefix * caches); mempool = (qmemlink *) P; For (INT I = 1; I <caches; ++ I) {r = (qmemlink *) P; P + = sizefix; r-> next = (qmemlink *) P;} r-> next = NULL; poolbytes + = (caches-1) * sizefix; usagebytes + = s; allocbytes + = caches * sizefix; returnp;} void free (void * P, size_t s) {qmemlink * l = (qmemlink *) P; l-> next = mempool; mempool = L; usagebytes-= s; poolbytes + = size;} voidstatus (uint64_t & U, uint64_t & A, uint64_t & P) const {u = usagebytes; A = allocbytes; P = poolbytes;} typedef qfixallocator me; static me instance ;}; typedefqfixallocator <pow ERT <2, 4>: Result> qfixallocator_4; typedefqfixallocator <powert <>: Result> qfixallocator_5; typedefqfixallocator <powert <>: Result> qfixallocator_6; typedefqfixallocator <powert <>: Result> failed; typedefqfixallocator <powert <>:: result> qfixallocator_9; typedefqfixallocator <powert <2, 10>: Result> qfixallocator_10; typedefqfixallocator <Po Wert <>: Result> qfixallocator_11; typedefqfixallocator <powert <>: Result> qfixallocator_12; typedefqfixallocator <powert <>: Result> qfixallocator_13; typedefqfixallocator <powert <>: Result> priority; typedefqfixallocator <powert <>: Result> qfixallocator_16; typedefqfixallocator <powert <2, 17>: Result> qfixallocator_17; typedefqfi Xallocator <powert <>: Result> priority; typedefqfixallocator <powert <>: Result> qfixallocator_19; typedefqfixallocator <powert <>: Result> qfixallocator_20; typedefqfixallocator <powert <2, 21>: Result> qfixallocator_21; Priority: instance; qfixallocator_13qfixallocator_13: instance; QF Ixallocator_14qfixallocator_14: instance; region: instance; qfixallocator_21qfixallocator_21: instance; template <Class Host> classqmemimpl {public: void * operatornew (Size_t size) {returnqfixallocator <powert <2, logt <sizeof (host), 2 >:: result >:: instance. alloc (size);} voidoperatordelete (void * P) {returnqfixallocator <powert <2, logt <sizeof (host), 2 >:: result >:: instance. free (p, sizeof (host);} void * operatornew [] (size_t size) {size + = 8; // x64 8-byte alignment ulongr, F; _ bitscanreverse (& R, size); _ bitscanreverse (& F, size); If (R! = F) // alignment + + R; Switch (r) {case19: // only the allocation of 1 MB bytes is processed here {uint32_t * P = (uint32_t *) qfixallocator_20 :: instance. alloc (size); * P = 19; // set mask ++ P; * P = size; return ++ P;} default: debugbreak ();} throw "Bad alloc";} voidoperatordelete [] (void * P) {uint32_t * p32 = (uint32_t *) P; p32-= 2; Switch (* p32) {case19: // only qfixallocator_20: instance. free (p32, * (p32 + 1); return; default: debugbreak () ;}}; template <Class Host> classqmemdebugimpl {Pu BLIC: void * operatornew (size_t size) {qmemdebuginfo * P = (optional *) qfixallocator <powert <2, logt <sizeof (host) + sizeof (qmemdebuginfo), 2> :: result>: instance. alloc (size); memset (p-> guard, 0, sizeof (p-> guard); P-> mask = logt <sizeof (host) + sizeof (qmemdebuginfo ), 2 >:: result; P-> mask | = 0x12345600; P-> size = size; return ++ P;} voidoperatordelete (void * P) {qmemdebuginfo * pdebug = (qmemdebuginfo *) P; -- pdebug; If (pdebug-> m Ask &(~ 0xff ))! = 0x12345600) {// The flag is incorrect. It may be the use of Delete, new [] debugbreak ();} If (pdebug-> size! = Sizeof (host) {// size error debugbreak ();} // other checks returnqfixallocator <powert <2, logt <sizeof (host) + sizeof (qmemdebuginfo ), 2 >:: result >:: instance. free (pdebug, sizeof (host);} void * operatornew [] (size_t size) {size + = sizeof (qmemdebuginfo); ulongr, F; If (! _ Bitscanreverse (& R, size) debugbreak (); // size 0, which is impossible _ bitscanreverse (& F, size); If (R! = F) // align + + R; qmemdebuginfo * P; Switch (r) {case19: P = (qmemdebuginfo *) qfixallocator_20: instance. alloc (size); P-> mask = 19; break; case20: P = (qmemdebuginfo *) qfixallocator_21: instance. alloc (size); P-> mask = 20; break; default: debugbreak ();} memset (p-> guard, 0, sizeof (p-> guard )); p-> size = size; return + P;} voidoperatordelete [] (void * P) {qmemdebuginfo * pdebug = (qmemdebuginfo *) P; -- pdebug; if (pdebug-> mask &(~ 0xff) {// The flag is incorrect. It may be caused by the use of Delete [], newdebugbreak ();} If (pdebug-> size <sizeof (host )) {// size error debugbreak () ;}ulongr, F; _ bitscanreverse (& R, pdebug-> size); _ bitscanreverse (& F, pdebug-> size ); if (R! = F) ++ R; If (pdebug-> mask! = R) debugbreak (); Switch (pdebug-> mask) {case19: qfixallocator_20: instance. free (pdebug, pdebug-> size); return; case20: qfixallocator_21: instance. free (pdebug, pdebug-> size); return; default: debugbreak () ;}}; template <Class Host> classqmempool: Public typeselectt <debugqmem, qmemdebugimpl