I sit around and think about whether or not I should be using const char*
or const std::string&
pretty often when I'm designing class interfaces and when it comes down to it, I often feel like there's 6 in one hand with half a dozen in the other.
Take the following two function prototypes:
void foo(const char* str);
void foo(std::string str);
If the foo
function were to store a string, I would say the second is a better option due to the ability to pass a string and utilize move semantics where possible. However, if foo
only needed to read the string, would the const char*
solution be better?
On a performance perspective, a temporary std::string
wouldn't need to be created. However, calling the function with an already existing string as an argument looks obtrusive: foo(mystr.c_str())
. Worse yet, if more advanced operations need to be done on the array at some point down the road or if a copy should be stored, the interface then has to change.
So my questions is this:
Are there well defined, either personal or otherwise, conventions that rule when std::string
or const char*
is a better choice? Furthermore, when starting a new project, is it best to be consistent with usage or just take whichever one fits the current chunk of code best?
const char*
is a throwback to C. I'd say that in decent C++, about the only use for it is in extern "C"
APIs.
std::string
has a number of advantages:
It provides a constant-time size()
function. Discovering the length of a const char*
takes linear time.
It is guaranteed to be valid. A const char*
has to be checked for being null, and it is entirely possible to pass incorrect data - data missing a null terminator. Such an occurrence is pretty much guaranteed to result in a crash or worse.
It is compatible with standard algorithms.
If you're worried about performance impacts of having to create a std::string
to call the function, consider taking the approach the standard library uses - change the function to take a pair of iterators instead. You can then provide a convenience overload taking a const std::string&
delegating to the iterator-pair one.