It is not copied, it is moved.
The return statement is equivalent to this:
return std::move(p);
Pedantically speaking, that is semantically equivalent. In reality, the compiler may optimize the code, eliding the call to the move-constructor. But that is possible only if you write it as:
return p; //It gives the compiler an opportunity to optimize this.
That is recommended. However, the compiler has no opportunity to optimize if you write this:
return std::move(p); //No (or less) opportunity to optimize this.
That is not recommended. :-)