Home > Mobile >  Will "copy elision" and "named return value optimization (NRVO)" work in a recur
Will "copy elision" and "named return value optimization (NRVO)" work in a recur

Time:12-07

In C , compilers are specifically allowed to perform "copy elision," and more specifically "named return value optimization," (NRVO) such that a function-local variable isn't even move()'d to a variable in the caller's stack frame, but is in fact itself in the caller's stack frame.

Can this be assumed to work with recursive functions? Or should I have the caller manually pass in the storage?

vector<MyClass*> MyClass::GetHeirarchy() {
    vector<MyClass*> apclass;

    if ( pclassParent )
        apclass = pclassParent->GetHeirarchy();

    apclass.push_back( this );
    return apclass;    
}

Here's the same function written without assuming NRVO. Oddly, it seems shorter and simpler.

void MyClass::GetHeirarchy( vector<MyClass*>* papclass ) {

    if ( pclassParent )
        pclassParent->GetHeirarchy( papclass );

    apclass->push_back( this );
}

CodePudding user response:

There is no elision here:

apclass = pclassParent->GetHeirarchy();

This is assignment. It is always assignment. Elision is about the initialization of an object. apclass is already initialized at this point, so this just assigns to an existing object.

If you want elision to be possible within a recursive call, then you need to either return GetHeirarchy directly or use its return value to initialize a local that you then return with modifications.

But in general, the kind of algorithm you're implementing (where you're conceptually creating a single object through recursive manipulation of said object) is not something where elision will be generally helpful. The final object can be elided, but the various steps that manipulate the object should be done as clear object manipulation:

void MyClass::GetHeirarchyRec( vector<MyClass*>& apclass ) {

    if ( pclassParent )
        pclassParent->GetHeirarchyRec( apclass );

    apclass.push_back( this );
}

void MyClass::GetHeirarchy()
{
    vector<MyClass*> ret;
    GetHierarchyRec(ret);
    return ret;
}

This way, the user interface of just receiving an array is preserved.

  • Related