Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7743089
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T09:26:32+00:00 2026-06-01T09:26:32+00:00

Let’s say I want to implement a function that is supposed to process an

  • 0

Let’s say I want to implement a function that is supposed to process an object and return a new (possibly changed) object. I would like to do this as efficient as possible in C+11. The environment is as follows:

class Object {
    /* Implementation of Object */
    Object & makeChanges();
};

The alternatives that come to my mind are:

// First alternative:
Object process1(Object arg) { return arg.makeChanges(); }
// Second alternative:
Object process2(Object const & arg) { return Object(arg).makeChanges(); }
Object process2(Object && arg) { return std::move(arg.makeChanges()); }
// Third alternative:
Object process3(Object const & arg) { 
    Object retObj = arg; retObj.makeChanges(); return retObj; 
}
Object process3(Object && arg) { std::move(return arg.makeChanges()); }

Note: I would like to use a wrapping function like process() because it will do some other work and I would like to have as much code reuse as possible.

Updates:

I used the makeChanges() with the given signature because the objects I am dealing with provides methods with that type of signature. I guess they used that for method chaining. I also fixed the two syntax errors mentioned. Thanks for pointing those out. I also added a third alternative and I will repose the question below.

Trying these out with clang [i.e. Object obj2 = process(obj);] results in the following:

First option makes two calls to the copy constructor; one for passing the argument and one for returning. One could instead say return std::move(..) and have one call to the copy constructor and one call to the move constructor. I understand that RVO can not get rid of one of these calls because we are dealing with the function parameter.

In the second option, we still have two calls to the copy constructor. Here we make one explicit call and one is made while returning. I was expecting for RVO to kick in and get rid of the latter since the object we are returning is a different object than the argument. However, it did not happen.

In the third option we have only one call to the copy constructor and that is the explicit one. (N)RVO eliminates the copy constructor call we would do for returning.

My questions are the following:

  1. (answered) Why does RVO kick in the last option and not the second?
  2. Is there a better way to do this?
  3. Had we passed in a temporary, 2nd and 3rd options would call a move constructor while returning. Is is possible to eliminate that using (N)RVO?

Thanks!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T09:26:34+00:00Added an answer on June 1, 2026 at 9:26 am

    I like to measure, so I set up this Object:

    #include <iostream>
    
    struct Object
    {
        Object() {}
        Object(const Object&) {std::cout << "Object(const Object&)\n";}
        Object(Object&&) {std::cout << "Object(Object&&)\n";}
    
        Object& makeChanges() {return *this;}
    };
    

    And I theorized that some solutions may give different answers for xvalues and prvalues (both of which are rvalues). And so I decided to test both of them (in addition to lvalues):

    Object source() {return Object();}
    
    int main()
    {
        std::cout << "process lvalue:\n\n";
        Object x;
        Object t = process(x);
        std::cout << "\nprocess xvalue:\n\n";
        Object u = process(std::move(x));
        std::cout << "\nprocess prvalue:\n\n";
        Object v = process(source());
    }
    

    Now it is a simple matter of trying all of your possibilities, those contributed by others, and I threw one in myself:

    #if PROCESS == 1
    
    Object
    process(Object arg)
    {
        return arg.makeChanges();
    }
    
    #elif PROCESS == 2
    
    Object
    process(const Object& arg)
    {
        return Object(arg).makeChanges();
    }
    
    Object
    process(Object&& arg)
    {
        return std::move(arg.makeChanges());
    }
    
    #elif PROCESS == 3
    
    Object
    process(const Object& arg)
    {
        Object retObj = arg;
        retObj.makeChanges();
        return retObj; 
    }
    
    Object
    process(Object&& arg)
    {
        return std::move(arg.makeChanges());
    }
    
    #elif PROCESS == 4
    
    Object
    process(Object arg)
    {
        return std::move(arg.makeChanges());
    }
    
    #elif PROCESS == 5
    
    Object
    process(Object arg)
    {
        arg.makeChanges();
        return arg;
    }
    
    #endif
    

    The table below summarizes my results (using clang -std=c++11). The first number is the number of copy constructions and the second number is the number of move constructions:

    +----+--------+--------+---------+
    |    | lvalue | xvalue | prvalue |    legend: copies/moves
    +----+--------+--------+---------+
    | p1 |  2/0   |  1/1   |   1/0   |
    +----+--------+--------+---------+
    | p2 |  2/0   |  0/1   |   0/1   |
    +----+--------+--------+---------+
    | p3 |  1/0   |  0/1   |   0/1   |
    +----+--------+--------+---------+
    | p4 |  1/1   |  0/2   |   0/1   |
    +----+--------+--------+---------+
    | p5 |  1/1   |  0/2   |   0/1   |
    +----+--------+--------+---------+
    

    process3 looks like the best solution to me. However it does require two overloads. One to process lvalues and one to process rvalues. If for some reason this is problematic, solutions 4 and 5 do the job with only one overload at the cost of 1 extra move construction for glvalues (lvalues and xvalues). It is a judgement call as to whether one wants to pay an extra move construction to save overloading (and there is no one right answer).

    (answered) Why does RVO kick in the last option and not the second?

    For RVO to kick in, the return statement needs to look like:

    return arg;
    

    If you complicate that with:

    return std::move(arg);
    

    or:

    return arg.makeChanges();
    

    then RVO gets inhibited.

    Is there a better way to do this?

    My favorites are p3 and p5. My preference of p5 over p4 is merely stylistic. I shy away from putting move on the return statement when I know it will be applied automatically for fear of accidentally inhibiting RVO. However in p5 RVO is not an option anyway, even though the return statement does get an implicit move. So p5 and p4 really are equivalent. Pick your style.

    Had we passed in a temporary, 2nd and 3rd options would call a move
    constructor while returning. Is is possible to eliminate that using
    (N)RVO?

    The “prvalue” column vs “xvalue” column addresses this question. Some solutions add an extra move construction for xvalues and some don’t.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Let's say we have a simple function defined in a pseudo language. List<Numbers> SortNumbers(List<Numbers>
Let's say I have a drive such as C:\ , and I want to
Let's say I'm writing a PHP (>= 5.0) class that's meant to be a
Let's say that we have an ARGB color: Color argb = Color.FromARGB(127, 69, 12,
Let's say I have the following object: var VariableName = { firstProperty: 1, secondProperty:
Let's say I have multiple requirements for a password. The first is that the
Let's say that I have a date in R and it's formatted as follows.
Let's say that I have a set of relations that looks like this: relations
Let's say I have the following function in C#: void ProcessResults() { using (FormProgress
Let's say I dynamically create a timer like this: System.Timers.Timer expirationTimer = new Timer(expiration

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.