Without having looked in-depth in your code I would say to use std::vector instead of new/delete (in fact you forgot to call delete) and to use std::uniform_int_distribution instead of rand() % n. The latter can introduce biasbias however it is not very important in this example.
Also to answer your pointer question I always implement merge sort bottom-up. You can allocate your \$\mathcal{O}(n)\$ extra space once and only once and then by swapping pointers you can avoid copying the sorted array back to itself except potentially at the end.