If your function returns a reference to an object that shouldn't have been copied, then your function already has done what it could do to prevent copying. If someone else calls your function and copies the return value, then either
- it's an error the caller made, because the object should never be copied (in which case the return type probably shouldn't have been copyable in the first place), or
- it's irrelevant for the caller because the function is only called once in a week (in which case you must not try to cripple your callers' code), or
- it's a pretty dumb oversight on the side of the caller (in which case the error will be found by profiling).
For #1, either you return have your own type or you can wrap whatever your return in your own type. Note that the only difference between #2 and #3 is the relevance - and if it's relevant, profiling will find it.
IMO you should not cripple your code by returning a pointer when what you need is a reference. Experienced programmers, seeing the pointer, will immediately ask whether they need to check for a NULL
return value, whether the object is allocated dynamically and, if so, who is responsible for cleaning it up.
You should also not blindly forbid copying of whatever you return, if you cannot eliminate the possibility that copying is needed.
In the end it's the old motto, which C++ inherited from C: Trust your users to know what they are doing.