2

Within C++ it is common to pass by reference instead of pointer if a value can not be NULL.

Suppose I have a function with the following signature, which is often used with a string literal.

void setText( const char* text );

I was wondering how I could change the function in such a way that it accepts a reference (and has the advantage not to accept NULL)?

  • If I would change it to (const char& text) then it would be a ref to a single char. From which the address can ba taken inside the function... but feels not nice.

  • Another option would be (const std::string& text) which has the disadvantage that it always calls a constructor and does some dynamic memory allocation.

Any other common ways, or just stick to the std::string& or the char* ?

Filip Roséen - refp
  • 62,493
  • 20
  • 150
  • 196
Waldorf
  • 833
  • 2
  • 13
  • 24
  • 1
    Take a `const std::string &`. It will be automatically constructed from a C string. "it always calls a constructor and does some dynamic memory allocation" – most likely no, if you're using a reasonable standard library and compiler. – The Paramagnetic Croissant Dec 08 '14 at 19:58
  • Look around for a `string_ref`. I don't think its standard but it makes a light reference wrapper for `std::string` or `const char*`. – Zan Lynx Dec 08 '14 at 19:59
  • `const std::string&`, this is where RAII really helps you out. – OregonTrail Dec 08 '14 at 20:01
  • string literals are char arrays so you could take an array by reference templated on the array size. I don't think I'd prefer such a template solution over `std::string` though. – AliciaBytes Dec 08 '14 at 20:11
  • If you are using C++11, you can create a `setText(const char * text)` -- with the reference advantages and a `setText(std::nullptr_t)` to handle NULLs. – user666412 Oct 15 '15 at 14:13
  • 2
    @user666412: overrides are determined at compile time so a nullptr_t would only catch calls using a literal null. – Zan Lynx Oct 19 '15 at 19:21
  • Um this is _not_ why we choose references over pointers. If your function takes a pointer that must not be null, simply document that as a precondition. – Lightness Races in Orbit Oct 19 '15 at 19:35

2 Answers2

2

Honestly, I would just keep the const char* text function and add an overload const std::string& text function that calls the first one with setText(text.c_str())

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
-1

There's a slight problem here in that C++ and references-to-arrays aren't the best pair. For reference, see: C++ pass an array by reference

Since you're talking about binding a reference to a string, and a string is an array of characters, we run into that problem head-on. In light of this, the best we can really do is bind a ref to a const char*, which looks like this:

void ref(const char* const& s);

But this doesn't do what you want; this binds a reference to a pointer, and all it guarantees is that the pointer itself exists, not that it's pointing to a valid string literal. This same problem is present in the std::string& examples: those only guarantee that you've bound to a std::string object, but that string could very well be empty, so you still haven't guaranteed yourself a string that has anything of value in it.

In the end, I'll second what Zan says. const char* is a well respected idiom passing string literals, and then having a second overload that binds to strings is a nice convenience.

(One last note: std::string doesn't "always" allocate memory. Implementations with the small string optimization will skip it for strings as long as 23 characters.)

Community
  • 1
  • 1
JHumphrey
  • 958
  • 10
  • 15