Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the C++ NVRO applicable with object slicing or with a local object data member?

Copy elision starts to become more and more mandatory with each new C++ standard. However, the conditions into which it is applicable are not always obvious and I need help to better understand them to arrange my code in a way that I do take advantage of it.

I was using RVO in the following manner:

/*
 * Simplified version of the real thing for the sake of discussion
 */
class Update
{
public:
    Update(double v1, double v2)
    {
        m_values[0] = v1;
        m_values[1] = v2;
    }
private:
  m_values[2];
};

/*
 * handler called during a stream-oriented parsing
 */
class ParserHandler
{
public:
    double getV1() const;
    double getV2() const;
};

Update buildRecord()
{
    ParserHandler handler;

    parse(handler);
    return Update{handler.getV1(), handler.getV2()};
}

but I was unsatisfied after the realization that the class ParserHandler was essentially containing a duplicate of the returned update object.

I came with the following. When I wrote it, I was sure that NVRO would kick in but I am not so sure anymore that the standard or my compiler (gcc) will do the optimization:

Idea #1:

/*
 * handler called during a stream-oriented parsing
 */
class ParserHandler
{
public:
    Update m_workingUpdate;
};

Update buildRecord()
{
    ParserHandler handler;

    parse(handler);
    return handler.m_workingUpdate;
}

Idea #2:

/*
 * handler called during a stream-oriented parsing
 */
class ParserHandler : public Update
{
};

Update buildRecord()
{
    ParserHandler handler;

    parse(handler);
    return handler;
}

So the question is: will the C++ NVRO kick in in one or both of those 2 setups and if not, what is the best way to minimize copying around the Update return value?

like image 437
lano1106 Avatar asked Nov 18 '25 17:11

lano1106


1 Answers

Idea #1:

Elision in a return <expr>; statement only if <expr> names a local variable. handler.m_workingUpdate names a subobject of a local variable, not a local variable itself. So no elision.

Idea #2:

Elision in a return <expr>; statement only applies if the type of the named local variable exactly matches the return type (minus cv-qualifiers). handler is of type ParserHandler, which is not the same type as Update. So again, no elision.

like image 97
Nicol Bolas Avatar answered Nov 21 '25 07:11

Nicol Bolas