Short for constant. Used in several computer languages, including C and C++, when a variable is meant to retain the same value throughout the program. Often universal.

C++ offers concise, precise and utterly bewildering usage for the const modifier on types. Enough so that this note could just as well have been a part of the freakshow. Beginning C++ programmers often ask themselves what a "const pointer" should be.

"It depends".

Assume these declarations:

T* q;
T gimme_T;
  • If you want the variable holding the pointer not to change its value (a constant pointer), you need to say T* const p = &some_T;. Now p = q; is an error (you must initialize p, but you cannot assign to p), but *p = gimme_T; is fine.
  • If you want the object at which the pointer points not to change its value (a pointer to constant data), you need to say const T* p;. Now p = q; is fine (p will look at the same thing as q does), but *p = gimme_T(); is an error: you cannot modify via p;.
  • To make for interesting interview questions, as well as for actual use in the field, the form const T* const p also exists. This declares p as a constant pointer to constant data. Both p=q; and *p = gimme_T(); are not allowed.
  • Since things are too simple for an industrial grade language like C++, const T means the same thing as T const. Other than that, C++ const declarations follow the old C "inside-out" declaration syntax.

C++ also allows you to declare a class method as "const". This qualifier indicates that the method may be used on a const-qualified reference to the type:

// not the real declarations, which are far more baroque!
template<typename T>
class vector<T> {
  // ...
public:
  // ...
  typedef something iterator;
  typedef something else const_iterator;
  // ...
  iterator begin();
  const_iterator begin() const;
  iterator end();
  const_iterator end() const;
  // ...
};
Gorgonzola points out that this is semantic overloading at its best.

If a const vector<double> (1) allowed you to get an iterator pointing at its first element (2), then you could subvert constness and modify that element (3) by saying

const vector<double> v = gimme_vector(); // (1)
vector<double>::iterator i = v.begin();  // (2)
*i = 3.14159265;                         // (3)
Obviously, we can't have that. But examining the method declarations above shows that a const vector only has a begin() method returning a const_iterator. So the assignment in (2) cannot be instantiated, giving a compilation error. You could instead say in (2) "vector<double>::const_iterator i = v.begin();", but then (3) would fail -- dereferencing a const_iterator gives a const reference, which isn't assignable!

The const modifier for methods lets us make this important distinction at the right place. Of course, it does mean that C++ does with const what it rightly slams C for doing with static -- hideous semantic overloading, of vaguely-related concepts.


Modern ISO C also has this modifier. It is almost, but not quite, wholly unlike the modifier in C++. The general rules for its use are similar to those for C++, except...

  • There is no overloading of functions by type, therefore no overloading by constness. So the declaration of the standard function strchr is
    char *strchr(const char *s, int c);
    
    which is nonsense!

    strchr takes a pointer to a constant string, and returns a pointer to a string -- it allows you (from the type-checking point of view, though not really, because the language forbids it...) to convert a constant string to a mutable string.

    It has to do this: we want to call strchr on constant strings, so its argument must have type const char *. And we want to be able to modify via its return value pointer when called with a mutable string, so its return value must have type char *. Oops.

    C++ solves the problem by overloading on the argument type. This is also ugly, but less, and in different ways.

  • const variables are really variables not constants.
  • To get a real constant, at least for an integer, you need to use an enum (similar to the C++ enum hack).

It's worth noting that const behaves completely differently in C and C++. In C, it behaves more like a "special" global variable. That is to say, you can declare a constant in one file and use "extern" to access it in another file. You also can't do this:
const int ARRAYSIZE = 10;

int array[ARRAYSIZE];
In the C++ world, everyone hates the preprocessor, so Stroustrop "hijacked" the const keyword to replace the use of #define for constants. All constants are module-local (like they had the "static" keyword used). To get the same behavior as is default in C, you have to do something like this:
extern int EXTERNALLY_ACCESSIBLE_CONSTANT = 1337;
This means that you can put constants into header files more easily.

The designers of Java quite understandably wanted nothing to do with all this mind-breaking inconsistency, which is why constants in Java use the keyword "final" instead.

Y'know, if you log in, you can write something here, or contact authors directly on the site. Create a New User if you don't already have an account.