I expected that
ptr[3]
should goes beyond the range of newly allocated memory.
It does indeed. You need to be careful not to do that, since (as you've noticed) that's an error that often can't be detected. Dynamic analysis tools like valgrind can help diagnose these problems, but not perfectly.
However, the result still give 2.
That means that there happened to be accessible memory beyond the end of the array, so the invalid access couldn't be detected. Instead, it overwrote memory that didn't belong to the array - perhaps it was unused, or perhaps you've overwritten some other data, which will cause baffling errors later.
Why the pointer arithmetic become useless?
It's as useful as any pointer arithmetic. Pointer arithmetic can't detect the end of an array, so you get undefined behaviour if it takes you out of range.
Or is it really
new Type
returns an object of*Type
?
new Type[]
returns a Type*
pointer to the allocated array. That behaves just like any other pointer, so adding one gives you a pointer to the second element.
delete [] ptr
also gives undefined behaviour, since ptr
no longer points to the start of an allocated array.