Search code examples
c++stringobject-lifetime

Convert to std::string and get const char * in one line


I have a number that I need to convert to a const char * (an API I'm using them requires const char * as input to many of its functions). The following works:

int num = 5;
std::string s = std::to_string(5);
const char * p = s.c_str();

as suggested by answers like those in how to convert from int to char*?, but it involves creating the seemingly unnecessary variable s, so I tried the following, but it doesn't work (p points to an empty string afterwards):

int num = 5;
const char * p = std::to_string(num).c_str();

Is there a clean way I can accomplish this? Why doesn't the second example work? The behavior is very similar to what happens if I made this obvious mistake:

const char * p;
{
    std::string tempStr( "hi" );
    p = tempStr.c_str( );
    // p points to "hi" string.
}
// now p points to "" string.

Which makes me suspect that the issue std::to_string(num) immediately goes out of scope or something similar because it's not used to directly initialize anything.


Solution

  • std::string encapsulates managing dynamic memory (created with new[] and delete[]). Let's break it down.

    const char * p = std::to_string(num).c_str();
    
    1. Create a std::string (with a human-readable representation of num).
    2. Get the new[]ly allocated const char* to the string.
    3. Assign that value to p.
    4. Destroy the std::stringdelete[] the allocated const char*.
    5. p points to... deallocated data

    If you are using a pointer, the data that the pointer points to must exist throughout the lifetime of that pointer.

    So, no, there is no way around this other than new[]ing a copy of the string, which you will have to explicitly delete[] later. And at that point, you've thrown the baby out with the bath and have no need to use std::string.

    Create a string that lives at least as long as you want to refer to its internal data.