CaptainTid CaptainTid - 3 months ago 9
C++ Question

Can't successfully return a const char* I have created by calling c_str() on a string. (C++)

I have a class in my program that has a member variable, an int called number, and a member function, getName(), that is MEANT to return the words "Dice: #" as a const char*, but with the # replaced by the number stored in the class.

const char* getName(){
return "Dice:";
}


works perfectly well.

const char* getName(){
std::stringstream ss;
ss << number;
std::string s;
s = "Dice: " + ss.str();
return s.c_str();
}


does NOT work fine, and returns what seems to be garbage. I can't figure out the correct way to go about this. If I use cout to print
s.c_str()
it prints what I expect.

Answer

The short and sweet answer is that you can't do this, the way you've set this up.

The std::string object from which you retrieve your c_str() is in the function's local scope. When the function returns that std::string object gets destroyed.

That

std::string s;

is a local function object. When the function returns it ceases to exist. It joins the choir invisible. It is no more. It's an ex-object.

And when a std::string object gets destroyed, any of its c_str()s are no longer valid. This is why you're getting garbage: undefined behavior.

There is no way to do this without changing the overall design of it, in some way. There are many ways to go forward. Some of the possibilities:

Return a std::string in the first place

Just return the std::string from getName(). Whoever calls it can store this std::string, for a while, and grab it's c_str() if it needs it.

Use a std::string with a different scope

If this getName() is a class method, you could have a private std::string class member, have getName() store the string there, and return its c_str().

Because the original std::string continues to exist, the returned c_str() remains valid. Note that there are some pitfalls here. If the caller calls getName() again, the previously-returned c_str() will no longer be valid.

Conclusion

Just get in the habit of using and working with std::strings in your C++ code. That's what they're for.

The name "c_str()" should be a clue. It gives you a string to be used with C code, if there's any C code lying around, in the near vicinity. It's a C string. Are you writing C code here? No, you're writing C++ code.

Unless you're writing C code, or are talking to a C library, there's no need to use c_str() in the first place. If you're writing C++ code, you should be using std::strings. If you need to call a C library function, call c_str() to pass the appropriate C library function parameter, and speak of this C string no more.