berglerma (1) [Avatar] Offline

I think the part
returning a const object will incur a copy instead of being able to just move it into the result

might be misinterpreted as

person_t some_function() {
    person_t const result;
    // do some work
    return result;

being a problem (we're returning a const object), whereas what you meant was the return type being const qualified, as in

person_t const some_function() {
    person_t result;
    // do some work
    return result;

The latter will result in a copy when assigning the return value of this function to a non-const person_t variable as in
int main() {
    person_t pers{some_function()};
Ivan Cukic (99) [Avatar] Offline
I was actually referring to the first one.

If a function returns a class type by value, and the return statement's expression is the name of a non-volatile object with automatic storage duration, which isn't the function parameter, or a catch clause parameter, and which has the same type (ignoring top-level cv-qualification) as the return type of the function, then copy/move is omitted. When that local object is constructed, it is constructed directly in the storage where the function's return value would otherwise be moved or copied to. This variant of copy elision is known as NRVO, "named return value optimization".

If NRVO fails, the only things left for the compiler to try are move and copy. If the local variable is const, we will not be able to move from it.