3

I have a method that ultimately will take a value from an internal api call

auto val = api->post(req);  //step 1

// the post returns a class of "type json"

json api::post(const request& request) { //step 2

   // do some job
   json j = << some json data>>
   return j;

}

Now there is a third step that prepares the http response back to the external caller.

response server::http_response(const json &final_jsond) {

    auto response = response{final_json}; //that makes the json a string for the http payload
    response.set_header("Content-Type", "application/json");

    return response;
}

Now, this code works, however I am wondering if I am missing some modern C++ principles in order to avoid copying the json object from one call to another

Can the above code be optimized by using modern c++ methods to become faster?

returning by reference maybe?

L. F.
  • 19,445
  • 8
  • 48
  • 82
Captain Nemo
  • 345
  • 2
  • 14
  • 6
    The three main compilers are all good at RVO (Return Value Optimization) like for example copy-elision. And you could possible use "move" constructors and `std::move` to avoid copying as well. – Some programmer dude Jul 23 '19 at 07:05
  • wy don't you return by reference? – nivpeled Jul 23 '19 at 07:09
  • 4
    @nivpeled a reference to what, to a local variable? That would be a bad idea. – t.niese Jul 23 '19 at 07:11
  • 1
    @nivpeled because that would generate a problem. – Michael Chourdakis Jul 23 '19 at 07:11
  • 2
    Btw, returning by reference was there since a long time ago before the **modern** C++ comes. It has nothing to do with the modern stuff. – Dean Seo Jul 23 '19 at 07:20
  • Everything looks normal taking into account RVO. You can consider to pass arguments by rvalue ref (e.g. maybe response has mv-ctor?). But from your code I don't think it will give you anything. By const reference looks good for this example. – Roout Jul 23 '19 at 07:23
  • 1
    unless sizeof(...) is big then just ensure that you have a move constructor and return by value. You don't need std::move here – Sopel Jul 23 '19 at 09:36
  • I am passing by value and constructor of response std::move(final.to_string)) – Captain Nemo Jul 23 '19 at 09:40

1 Answers1

0

As others have suggested, the return should be OK as written. If it's reasonable for server::http_response to consume its argument and if response actually holds onto a json or onto data in it, then you could do

response server::http_response(json&& final_json) {
    auto response = response{std::move(final_json)}; //that makes the json a string for the http payload
    response.set_header("Content-Type", "application/json");

    return response; // You don't need std::move here.
}

I use this pattern sometimes when copying is expensive. It forces the caller to do myResponse = myServer.http_response(std::move(final_json));, which is desirable for performance. If the caller wants to keep their json object, then they can instead call myServer.http_response(json(final_json));. Put another way, if http_response takes an rvalue reference, then the caller can provide it either by std::moveing or by constructing an unnamed temporary. But then the inefficiency of copying is on the caller.

PS

Have you measured this to be a performance bottleneck?

PPS

Having response be a type name and a variable name is a questionable choice.

Ben
  • 9,184
  • 1
  • 43
  • 56