The pointer returned by std::string::c_str
is only valid as long as the corresponding std::string
object is alive. So you can not return that pointer from your function. There is nothing wrong with that. If you want a copy you have to provide your own memory and copy the data over.
To accomplish that you can use several different methods.
The good ones care about ownership and use interfaces which are hard to misuse.
Version 1 (primitive):
char* foo() {
std::string a = "blah";
return strdup(a.c_str());
}
This looks easy enough, however who cares about deleting the memory allocated by strdup
? It is very likely, that the user of your function will forget to call free
.
Version 2 (C++11):
struct free_delete { void operator()(void* x) { free(x); } };
template<typename T> using unique_c_ptr = std::unique_ptr<T,free_delete>;
unique_c_ptr<char[]> foo() {
std::string a = "blah";
return unique_c_ptr<char[]>(strdup(a.c_str()));
}
auto p = foo();
char* cp = p.get(); // gets raw pointer
This uses a smart pointer to automatically delete the memory when out of scope. unique_ptr
models "unique" ownership, meaning there will always be exactly one owner. If that is too restrictive you can also use shared_ptr
.
Version 3 (C-style):
void foo(char* buffer, size_t size) {
std::string a = "blah";
strncpy(buffer, a.c_str(), size);
}
char buffer[128];
foo(buffer, 128);
In this version the caller is explicitly responsible for managing the memory. He can store the result wherever he likes. It has the downside, that the user must guess a good buffer size...