Find The Right Place For Const Qualifier In Declaration

The keyword const is a qualifier used to claim the values of variables are constant. It is useful, because compiler recognizes it and help programmers to avoid some bugs made unconsciously. However, I am always confused about where to put the const, especially using it with special types, for example pointer. This post is about declarations with const qualifier (also applicable to volatile of course).

Constant Pointer or Pointer to Constant

With four components, const, int, asterisk, and variable name, here could come 24 arrangments. The above two are legal and meaningful declarations. How to remember the correct order and mix the meaning? Someone say read from right to left, someone say break at asterisk and see whether const is together with type name or variable name.

Generally, there is one rule should be kept in mind, when making declarations in C or C++, called “Clockwise/Spiral Rule”.

  1. Starting with the unknown element, move in a spiral/clockwise direction; When ecountering the following elements replace them with the corresponding english statements:
    • [n] or [] => array n size of … or array undefined size of …
    • (type1, type2) => function passing type1 and type2 returning …
    • * => pointer(s) to …
  2. Keep doing this in a spiral/clockwise direction until all tokens have been covered;
  3. Always resolve anything in parenthesis first!

To better illustrate the “Clockwise/Spiral Rule”, here comes an example:

The declaration is about: what is fp? “fp is a …

  • Moving in a piral clockwise direction, the first thing we see is a ‘)’; therefore, fp is inside parenthesis, so we continue the spiral inside the parenthesis and the next character seen is the ‘*’, so
    “fp is a pointer to …
  • We are now out of the parenthesis and continuing in a spiral clockwise directoin, we see the ‘(‘; therefor, we have a functions, so …
    “fp is a pointer to a function passing …
  • Hmmm, we can use the same rule to resolve pci first, so … What is pci? pci is also inside parenthesis so continuing we see an ‘*’, so …
    “pci is a pointer to …
  • Continue in a spiral clockwise direction and we get to const int, so …
    “pci is a pointer to constant int”
    “fp is a pointer to a function passing a pointer to constant int returning ..
  • Continuing in a spiral fashion, we then see the ‘*’ character, so …
    “fp is a pointer to a function passing a pointer to constant int returning a pointer to …
  • Continuing in a spiral fashion to visit left tokens, we get const, finally get double, so …
    “fp is a pointer to a function passing a pointer to constant int returning a pointer to constant double”

Constant Member Function

Apart from variable declarations, const may appears after the declaration of member function, meaning this member function would not make any change to the class. Another keyword mutable is able to reverse the claim: mutable marks a variable in class as an exception that can be modified by constant member function. Furthermore, cv qualifiers even participate in function overloading. Here comes an example:

But note a const qualifier can be used only for class non-static member functions.

Iterator for Constant Container

One more challenge is how to declare iterator for constant vector (vector of constant type makes no sense). There are several solutions, and the easiest one is using const_iterators. The solution template is like this:

You should prefer using != instead of < with iterators - the latter does not work with all iterators, the former will.

Other solutions are using indexes, or “range-for” in C++11, documented as follows (not verified though):

Credits