Í is byte 0xCD, which the Windows debug allocator writes into your 15 bytes of memory to indicate that it is uninitialised heap memory. Uninitialized stack would be 0xCC. The idea is that if you ever read memory and unexpectedly get this value, you can think to yourself, "hmm, I've probably forgotten to initialise this". Also, if you read it as a pointer and dereference it, then Windows will crash your process, whereas if an uninitialised buffer were filled with random or arbitrary values then sometimes by fluke you'd get a valid pointer, and your code might cause all kinds of trouble. C++ doesn't say what values uninitialized memory holds, and non-debug allocators won't waste time filling memory with special values for every allocation, so you must never rely on that value being there.
This is followed by 4 bytes of ý (byte 0xFD), which the Windows debug allocator uses to indicate an out-of-bounds region at the end of a buffer. The idea is that if you ever find yourself in the debugger writing to a region that looks like this, you can think "hmm, I've probably overrun my buffer here". Also, if the value has changed when the buffer is freed, the memory allocator can warn you that your code is wrong.
« is byte 0xAB, and þ is 0xFE. Presumably these are also intended as eye-catchers (they aren't plausible pointers or offsets, so they don't form part of the heap structure). I don't know what they signify, possibly more guard data like the 0xFD.
Finally, I guess, you've found a 0 byte, the 16th byte beyond the end of your 15 byte buffer (i.e. the 31st byte counting from the start of it).
Asking the question as "C++" without mentioning that you're on Windows suggests that this is how C++ behaves. It isn't, it's how one implementation of C++ behaves, with particular compiler options and/or linked dlls. C++ does not permit you to read past the end of the buffer, Microsoft is just being nice to you and letting you get away with it not crashing or worse.