qpid-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Alan Conway <acon...@redhat.com>
Subject C++ tip: use of const [ignore at will]
Date Thu, 02 Apr 2015 16:18:45 GMT
I'm looking at some code that has a bunch of const mistakes in it,
thought I'd offer a quick tip. 

The placement of const in C++ is confusing. The secret is that there is
actually a simple, logical rule for const with one wildly confusing
exception, and almost everybody uses the exception. The actual C++ rule

"const refers to the thing that comes _before_ it *except* if const is
the first thing in the declaration in which case it refers to the thing
_after_ it"

If you always put const *after* the thing it modifies, complex type
expressions are easy to read. Many (most?) programmers don't, I still
don't in Qpid because I don't want pile inconsistency on confusion. But
once you know the rule, you can mentally flip that first const around
and it all becomes clear. 

[Aside: The Sacred Rule of C++ is: "Never break any code written since
the dawn of C no matter how insanely complex the language becomes".
const-before works for simple expressions and was used in early C++. By
the time they realized it *doesn't* work for complex expressions, people
had written code so the Sacred Rule kicked in and now we have

const-before is clear enough for simple expressions:

    const int* p;  // Cannot use p to modify the int.

But what about this:

    const int* const p; // Huh? What?

Now look how easy it is to read if you stick to const-after:

    int const *p;        // int is const, cannot modify the int.
    int const *const p;  // int is const and * is const: cannot modify the int or make the
pointer point elsewhere
    int *const p;        // * is const: *can* modify the int but *cannot* make the pointer
point elsewhere

Here's the huh, what example again but now you can flip it:

    const int* const p; // Huh? What?
    int const * const p; // Ahhh, yes, int is const, * is const. Of course.

Some of the above examples are unrealistic though, let me explain. 

It is often useful to declare a pointer to a const value, so whoever gets the pointer can't
mess with the value:

   foo const *p // the logical way
   const foo *p // the ugly way

But there is *rarely* any point in making the pointer or reference
*itself* const. In particular it is *never* useful to make a function
parameter or return type const. These const are all utterly useless:

    foo *const f(const int i1, int const i2, foo *const p)

In C++ parameters are passed by value so a function can *never* change
its parameters, const or not. It can only change things the parameters
point (or refer) to.

However declaring that the things the parameters point/refer to *is*

     foo const* f(foo const* p, foo const& r)
     const foo* f(const foo* p, const foo& r) // The ugly version

It can be useful to declare pointers const if they themselves are being
pointed at or referred to or are part of something being pointed at or
referred to, but not if they are being passed as parameters.

References work like pointers insofar as declaring the thing they refer
to as const. Unlike pointers you can't declare the reference itself to
be const:

     int const &i = ...; // Good, can't use reference to change the int
     int& const i = ...; // WRONG, reference itself can't be const.

This is because references are already immutable, you can't change what
they refer to. C++ references are like pointers in a frilly dress and
high heels - prettier but less mobile.


To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org

View raw message