This is a follow up of this question. Suppose I write a C++ interface that accepts or returns a const string. I can use a const char* zero-terminated string:
void f(const char* str); // (1)
The other way would be to use an std::string:
void f(const string& str); // (2)
It's also possible to write an overload and accept both:
void f(const char* str); // (3)
void f(const string& str);
Or even a template in conjunction with boost string algorithms:
template<class Range> void f(const Range& str); // (4)
My thoughts are:
f("long very long C string");
invokes a construction of std::string which involves a heap allocation. If f
uses that string just to pass it to some low-level interface that expects a C-string (like fopen) then it is just a waste of resources.f
can call the other depending on what is the most efficient implementation. However we can't overload based on return type, like in case of std::exception::what() that returns a const char*.The question is: what is the preffered way? Is there any single guideline I can follow? What's your experience?
Edit: There is also a fifth option:
void f(boost::iterator_range<const char*> str); // (5)
which has the pros of (1) (doesn't need to construct a string object) and (2) (the size of the string is explicitly passed to the function).
If you are dealing with a pure C++ code base, then I would go with #2, and not worry about callers of the function that don't use it with a std::string until a problem arises. As always, don't worry too much about optimization unless there is a problem. Make your code clean, easy to read, and easy to extend.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With