2

The std::string accessors (back, front, at, and operator[]) have const and non-const overloads, as below:

char& x();
const char& x() const;

Why does the second version return a const reference, as opposed to simply returning the char by value (as a copy)?

According to the rules of thumb on how to pass objects around, shouldn't small objects be passed by value when there's no need to modify the original?

Community
  • 1
  • 1
Emil Laine
  • 41,598
  • 9
  • 101
  • 157

2 Answers2

10

Because the caller might want a reference to the char, that reflects any changes made to it through non-const avenues.

std::string str = "hello";
char const& front_ref = static_cast<std::string const&>(str).front();
str[0] = 'x';
std::cout << front_ref; // prints x
Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • changes to const object? – ixSci Jun 13 '15 at 16:51
  • 1
    @ixSci: No. You can have a const reference to a non-const object. See my updated example. – Benjamin Lindley Jun 13 '15 at 17:02
  • Sure, but doesn't it look too much contrived? I can't imagine such a case whatsoever. – ixSci Jun 13 '15 at 17:03
  • 3
    @ixSci: Just because you can't personally imagine a use case, doesn't mean the interface should be arbitrarily restricted. – Benjamin Lindley Jun 13 '15 at 17:05
  • Well, interface is done that way because of the consistency and because the `basic_string` template is not restricted to `char` only. It is obviously there not for some funny cases which no one will ever use. – ixSci Jun 13 '15 at 17:06
  • 1
    @ixSci: No, it's that way because there's no reason to arbitrarily restrict it. – Benjamin Lindley Jun 13 '15 at 17:11
  • I agree with that - there is no need for the restriction. I just pointed out that the example is too much contrived to be seriously counted as the reason to include such an interface to the class. – ixSci Jun 13 '15 at 17:23
  • @ixSci: Yeah. Probably. I was just demonstrating that you can have a const reference to a non-const object (your first comment seemed to indicate that you didn't know that). A more likely scenario would be returning a non-const member string from a function by const reference, and then the user might want a reference to one of its chars. – Benjamin Lindley Jun 13 '15 at 17:27
  • @ixSci: the example is there to illustrate the reason, and may not be the reason itself. – Michael Foukarakis Jun 13 '15 at 17:46
1

Because context.

You're dealing with a container and functions with names that imply specific positional data.

std::string s = "hello world?";
const auto& s1 = s.back();
s.back() = '!';

Returning a reference here provides flexibility, it's also consistent with the non-const variants and other stl containers. After all these functions are actually members of std::basic_string<char>.

Remember that "rule of thumb" is a guideline not a rule.

kfsone
  • 23,617
  • 2
  • 42
  • 74