Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Making all getters- return values const?

52 views
Skip to first unread message

JiiPee

unread,
Feb 4, 2016, 11:57:57 AM2/4/16
to
I was reading Sutters book where he adviced how to create a perfect
class. In one place he said that here:

class Human
{
public:
string getName() const { return m_name; }
private:
string m_name;
};

it should be:
const string getName() const { return m_name; }

instead so that the user cannot by accident try to set the temporary
variable like:

Human a;
a.getName() = "Peter";

So preventing this kind of "error" use. I kind of agree, but do you
people also think that all getters should be done like this (if they
return an temporary object)?

I do not see class makers doing this consistently.

Victor Bazarov

unread,
Feb 4, 2016, 5:45:38 PM2/4/16
to
On 2/4/2016 11:57 AM, JiiPee wrote:
> I was reading Sutters book where he adviced how to create a perfect
> class. In one place he said that here:
>
> class Human
> {
> public:
> string getName() const { return m_name; }
> private:
> string m_name;
> };
>
> it should be:
> const string getName() const { return m_name; }

Are you sure you didn't miss the reference indicator, like

const string& getName() const { return m_name; }

?

>
> instead so that the user cannot by accident try to set the temporary
> variable like:
>
> Human a;
> a.getName() = "Peter";
>
> So preventing this kind of "error" use. I kind of agree, but do you
> people also think that all getters should be done like this (if they
> return an temporary object)?
>
> I do not see class makers doing this consistently.

There is very little sense in qualifying the return value type. Code like

a.getName() = "Peter";

needs to be caught in a code review and either clarified with a comment
or removed.

V
--
I do not respond to top-posted replies, please don't ask

Alf P. Steinbach

unread,
Feb 4, 2016, 6:53:35 PM2/4/16
to
On 2/4/2016 5:57 PM, JiiPee wrote:
> I was reading Sutters book where he adviced how to create a perfect
> class. In one place he said that here:
>
> class Human
> {
> public:
> string getName() const { return m_name; }
> private:
> string m_name;
> };
>
> it should be:
> const string getName() const { return m_name; }

Like Victor, I suspect that you've inadvertently omitted an “&” here.

But maybe not, it depends when this was written.

Anyway, the “get” prefix is negative value verbiage in C++, I'm
surprised Herb used it.


> instead so that the user cannot by accident try to set the temporary
> variable like:
>
> Human a;
> a.getName() = "Peter";
>
> So preventing this kind of "error" use. I kind of agree, but do you
> people also think that all getters should be done like this (if they
> return an temporary object)?

This was once recommended by Scott Meyers. Then came move semantics, and
Andrei Alexandrescu declared that advice dead (actually, as I recall,
that was /before/ C++11, just with Andrei's own C++03-compatible move
semantics scheme called Mojo). There was a slightly memorable quote that
I don't recall, but anyway, if you make the return value `const` then it
can't be efficiently moved from, so that's ungood.


> I do not see class makers doing this consistently.

For modern coding it would be a sign of UNREASONED coding, actively
doing additional needless and generally negative value things because
one has seen it somewhere, associated with some measure of authority,
without understanding it or reasoning about it.

But before C++11 it could be good practice.


Cheers & hth.,

- Alf

JiiPee

unread,
Feb 4, 2016, 8:47:58 PM2/4/16
to
On 04/02/2016 22:45, Victor Bazarov wrote:
>> it should be:
>> const string getName() const { return m_name; }
>
> Are you sure you didn't miss the reference indicator, like
>
> const string& getName() const { return m_name; }

No I did not. Sutters example is not the same though, but similar:

const Complex operator++(int)
{
Complex temp(*this);
++*this;
return temp;
}

but his reasoning is the same as what I said.
ok, my example is not best becouse we could use ref there for sure,,,
but how about looking at Sutters code?

JiiPee

unread,
Feb 4, 2016, 8:51:02 PM2/4/16
to
On 04/02/2016 23:53, Alf P. Steinbach wrote:
> On 2/4/2016 5:57 PM, JiiPee wrote:
>> I was reading Sutters book where he adviced how to create a perfect
>> class. In one place he said that here:
>>
>> class Human
>> {
>> public:
>> string getName() const { return m_name; }
>> private:
>> string m_name;
>> };
>>
>> it should be:
>> const string getName() const { return m_name; }
>
> Like Victor, I suspect that you've inadvertently omitted an “&” here.

ok, my example was not the best, but there is a better example in my
Victors asnwer.

>
> But maybe not, it depends when this was written.
>
> Anyway, the “get” prefix is negative value verbiage in C++, I'm
> surprised Herb used it.

its mine....

>
>
>> instead so that the user cannot by accident try to set the temporary
>> variable like:
>>
>> Human a;
>> a.getName() = "Peter";
>>
>> So preventing this kind of "error" use. I kind of agree, but do you
>> people also think that all getters should be done like this (if they
>> return an temporary object)?
>
> This was once recommended by Scott Meyers. Then came move semantics,
> and Andrei Alexandrescu declared that advice dead (actually, as I
> recall, that was /before/ C++11, just with Andrei's own
> C++03-compatible move semantics scheme called Mojo). There was a
> slightly memorable quote that I don't recall, but anyway, if you make
> the return value `const` then it can't be efficiently moved from, so
> that's ungood.

ok, so not been able to move is worse than a danger that somebody does:
a.getName() = "Peter";

Alf P. Steinbach

unread,
Feb 4, 2016, 10:00:12 PM2/4/16
to
On 2/5/2016 2:50 AM, JiiPee wrote:
> On 04/02/2016 23:53, Alf P. Steinbach wrote:
>>
>> [const result value] was once recommended by Scott Meyers. Then
>> came move semantics, and Andrei Alexandrescu declared that advice
>> dead (actually, as I recall, that was /before/ C++11, just with
>> Andrei's own C++03-compatible move semantics scheme called Mojo).
>> There was a slightly memorable quote that I don't recall, but
>> anyway, if you make the return value `const` then it can't be
>> efficiently moved from, so that's ungood.
>
> ok, so not been able to move is worse than a danger that somebody
> does: a.getName() = "Peter";

Yes, a restriction on useful and sometimes critical functionality is
more important than preventing someone from doing a harmless silly thing.

On a personal note, I never adopted the `const` return value convention
in C++03, because I didn't see the point doing extra work and making the
code more verbose in order to prevent a (as I saw it) non-problem.

Scott Meyers made up for his (IMO) bad advice about result values, which
was in the way of move semantics, by posting in this very group a
critique of the then proposed rules for automatic generation of move
constructors and assignment operators. He pointed out more situations
where there was effectively a class invariant, and that a moved from
object should always be destructible and, if previously assignable,
still assignable (OK, a detail here or there may be wrong, I don't
remember this exactly). As a result the proposed rules were changed.


Cheers!,

- Alf

JiiPee

unread,
Feb 4, 2016, 10:41:19 PM2/4/16
to
On 05/02/2016 02:59, Alf P. Steinbach wrote:
> As a result the proposed rules were changed.

I guess the lesson is that do not read too carefully older C++ books

SG

unread,
Feb 5, 2016, 8:22:04 AM2/5/16
to
In my opinion: yes. Like Alf, I also never adopted that rule even
before move semantics. I didn't really see a need. But that was
pretty much the only item from Meyers' Effective C++ book (I've read
the 3rd edition) I disagreed with.

Anyhow, C++11 allows you to have the cake and eat it to -- at least
for your own custom types. So, you can get move semantics *and* avoid
unwanted assignments to temporary objects. This is achieved via ref
qualifiers:

class Blah {
public:
Blah() = default;
Blah(Blah const&) = default;
Blah& operator=(Blah const&) & = default; // copy to lvalue
Blah& operator=(Blah const&) && = delete; // copy to rvalue
};

Another approach would be to use a static analyzer that warns about
assignment to temporary objects. (I don't really know whether this
is actually done by any of the available tools but I'm sure a tool
like cppcheck can be easily changed to flag these kinds of assigments
if this isn't already supported.)

Cheers!
sg

Öö Tiib

unread,
Feb 5, 2016, 10:14:48 AM2/5/16
to
On the contrary, read very carefully! Otherwise you may misunderstand.

The book authors (I like Scott Meyers, Herb Sutter, Andrei Alexandrescu,
Daveed Vandevoorde and Bjarne Stroustrup YMMV) describe what they
think are more popular views, better patterns and safer idioms. Often
their opinions overlap, sometimes contradict and like with any other
person their opinions change over time. So nothing is holy truth
just present experiences (at time of writing) of fellow programmer.

You are the master so you decide what is in your toolbox and what is
not ... there are no programming paradigms that C++ can not be
made to support.
0 new messages