Search code examples
c++stringcharacter-arrays

When should std::string be used over character arrays?


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?


Solution

  • 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:

    1. It provides a constant-time size() function. Discovering the length of a const char* takes linear time.

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

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