开发者

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


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`
}


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).

You can make the compiler create a temporary value in the caller scope for you, so that the temporary lifetime corresponds to that of the expression where the temporary is created. Here is how:

struct TmpStr {
    mutable std::string s;
};

template<typename T>
char const* to_cstr(T value, TmpStr const& tmp = TmpStr()) {
    tmp.s = to_string(value); // your original function
    return tmp.s.c_str(); // tmp lives in the scope of the caller
}

int main() {
    printf("%s\n", to_cstr(1));
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜