Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what's the most efficient way to implement a returned calculated value in C++?

With the advent of rvalue references on top of Return Value Optimization, what would be the most efficient way to implement a core function like this? How can I improve this implementation or should I leave it alone?

template <typename T>
string
to_string(const T& t)
{ 
  stringstream ss;
  ss << t;  
  return ss.str();
} 

Obviously, I want to avoid copying or allocating memory if I can. TIA.

Edit: Thx to D. Rodriguez for that detailed answer. Now, I have a second part to my question. Is there a way to improve on this?

#define to_cstr( T ) (to_string( T ).c_str())

Of course I would like to avoid MACROs if I can, but if I copy and paste the template code above to return ss.str().c_str() and const char*, the temporary doesn't live long enough; although the code seems to run, valgrind complains (red light).

I haven't been able to come up with a cleaner solution than the MACRO above for to_cstr(). Any ideas how to improve, or should I also leave alone?

  • Ken
like image 323
kfmfe04 Avatar asked Oct 03 '11 13:10

kfmfe04


1 Answers

Just leave it alone, it is efficient as it is. Even with C++03 compilers, the compiler will optimize the copies away.

Basically the compiler will make sure that the object in the calling code to to_string, the return statement of to_string, and the return statement of ss.str() all take exactly the same memory location. Which in turn means that there will be no copies.

Outside of what the standard mandates, the calling conventions for the return statement of a function that returns by value an object that does not fit in the registers in all 32/64 compilers I know (including VS, gcc, intel, suncc) will pass a pointer to the location in memory where the function is to construct the returned object, so that code will be translated internally to something in the lines of:

// Not valid C++! Just for illustration purposes
template <typename T>
to_string( uninitialized<string>* res, const T& t ) {
   stringstream ss;
   ss << t;
   stringstream::str( res, &ss ); // first argument is return location
                                  // second argument is `this`
}
like image 96
David Rodríguez - dribeas Avatar answered Nov 14 '22 08:11

David Rodríguez - dribeas