A keyword or other means for asserting that a type (or a reference to a type) is (or ought to be) immutable, and/or an object method will not modify the state of the object. There are two strategies, in a C++ program, for using the ConstQualifier. One is to practice ConstCorrectness; the other is to AvoidConstCompletely. In general, any program can use a library which is ConstCorrect with minimal issues; however, a const correct program will have difficulty importing a library which practices AvoidConstCompletely. The C++ standard library is const-correct (though early versions of the C standard library are not--one of the biggest uses of CastingAwayConst is to call harmless functions like strcmp() on older C/C++ implementations, and get it to compile without warnings). As a result, AvoidConstCompletely is probably best done in application code. Sounds simple enough, but it gets VERY tricky..... and that's ignoring things like PhysicalConst''''''ness vs LogicalConst''''''ness. Programmers of FunctionalProgrammingLanguage''''''s can start chuckling now, because most of the following doesn't apply to them. In a language without SideEffect''''''s, everything is immutable, and the ConstQualifier doesn't apply. In languages (or expressions) that use the ValueModel, const is fairly straightforward. Once an object is constructed, it's state doesn't change. For AtomicObject''''''s (those which don't contain references to other objects), there is little controversy. C++ optimizes heavily based on const for ValueObject''''''s. Declaring something to be "const int foo=5" is as good as defining a macro or an enum (the old C way of declaring manifest constants). If you use the ReferenceModel for variables (or use pointers in a language such as C/C++), things start to get interesting. For example: * does const refer to the pointer itself (ie can the pointer be rebound to another object * or to the NullObject * or be subject to--god forbid--PointerArithmetic) * or to the object pointed to by the pointer? * (And don't get me started on pointers to pointers, or worse). In C/C++, by use of a truly horrible syntax, you can achieve both. foo *x = &someFoo; is a pointer to type foo. Both the pointer and the referent can change. const foo *x = &someFoo; is a pointer to type const foo. The pointer can change; however you cannot modify the foo through this pointer. (But wait, see below...) foo *const x = &someFoo; is a const pointer to type foo. The pointer cannot change but the object being pointed to can. And... const foo *const x = &someFoo; is a const pointer to type const foo. Neither pointer nor referent is allowed to change. Confused yet? So am I. I can remember the first two; I had to look the other two up. (Usually I use typedef when I need the last two cases....) ''This is why any C++ textbook worth it's salt will teach you to read types right-to-left; "const foo *const x" reads as "(x) [is a] (const) (pointer) [to a] (foo) [which is] const".'' -- FauxFaux Java has a keyword which resembles const, called "final". When applied to objects, it prevents the pointer (please don't harangue me about JavaHasNoPointers) from changing; but the state of the object being referenced can change all you want. Java also has reserved the keyword const. I'm not sure if that's for future expansion or to prevent it from being used ever. (Java also reserves goto, but it has been stated on numerous occasions that this was done to ensure goto never gets added to the language...) (It is also worth noting that, much like "static" in C/C++, the "final" keyword in Java is horrendously overloaded...) Don't go away! I've only started. One common mistake that C/C++ users make is that if a pointer (or reference in C++) is declared const (here meaning the referent cannot change, not the pointer itself) that the underlying object won't change. Wrong. All that means is that the object cannot change ''through that pointer or reference''. The following is perfectly legal. Foo *f = new Foo(5); const Foo *g = f; printf ("%d\n", g.getMyValue()); // a const method f.setMyValue(6); printf ("%d\n", g.getMyValue()); The output is (of course) 5 followed by 6. The const object g has changed. Since it is perfectly valid to have const and non-const references aliased to the same thing, one cannot assume that a const object won't change. Other than simple types (such as ints and strings), there is no notion of an ImmutableObject in C/C++. const-ness is much weaker than immutability. (And this is without CastingAwayConst -- if we do that then everything flies out the window.) C/C++ even allow the keywords const and volatile to be combined; and it makes perfect sense to do so! (In other words, I can't change the object, but someone else likely will; and do so asynchronous to my operation). (Some special purpose compilers, such as the C compilers that target commercial DSP processors, do sometimes assume that const = immutable, and implore the user not to alias const arrays. The latest C standard now has a restrict keyword which makes the same promise). But things get even MORE confusing. const is bad enough for atomic objects (those which contain no references to other objects; especially references to objects that might be shared). But what about: struct const_node { void *element; struct const_node *next; }; (No snickering, LispHippie''''''s). What does it mean to have a const struct const_node*? That the two pointers therein cannot change? Or that the things being pointed to (and their transitive closure) cannot be changed? In C/C++, it is the former; const-ness is a rather shallow concept. (Which means if the logical state of an object depends on objects that it points to; even a const operation can change that state!) When you start dealing with containers (intelligent ones, not dumb ones like C/C++ arrays), things get even worse. There are (potentially) three levels of constness (assuming the things being contained are AtomicObject''''''s; things get even worse if not). * const means that the structure of the container cannot change: no inserting, deleting, or altering keys (for associative containers) * const means that the individual cells of the container cannot be rebound to new objects; * const means that the state of the contained objects cannot change. Or combinations of the above. One of the ugliest objects of the C++ StandardTemplateLibrary is the ConstIterator. Suppose I have a vector of type const vector (which means the first two bullets above, but NOT the third). Now I need an iterator for such a creature. What is the type of the iterator? * is it const vector::iterator? No; that would be an iterator to a non-const vector. In other words, I could use the iterator to mutate the container (a type violation) but I couldn't use the iterator to traverse the container (a useless iterator). * Would it be vector::iterator? No; that would mean that I couldn't modify the contained Ts; but I could modify the container all I want (again, a type violation). * vector::iterator? That might prevent me from pointing individual cells of the container at different objects; but I could still insert or delete things (still a type violation). * The correct answer is vector::const_iterator. This type allows me to modify the contained T objects, but not modify the container itself. Ugh. -- engineer_scotty (Scott Johnson) ''Although const_iterator can be confusing, your explanation of const_iterator is a tad overcomplicated. Start with V, a vector of T (not T*) to avoid confusing the issue with pointers. A const_iterator for such a container does not allow you to modify the objects of type T contained in V. ''No'' iterator allows you to insert or delete things in a container; iterators are for accessing individual elements, not the container itself.'' ''So:'' std::vector vint(1, 3); // init with one element, value "3". std::vector::iterator i = vint.begin(); *i = 5; // OK std::vector::const_iterator ci = vint.begin(); *ci = 6; // Error! ''That's all there is to it, basically. Derferencing a const iterator of vi yields a int const, which you can't modify. And you can't insert or delete elements from vi using just one of the iterators.'' ''Now if T happens to be of pointer type, e.g. vector, a const iterator prevents you from modifying the ''pointers'' in the container. They're what the container contains, after all -- no conceptual leap necessary. What might be a little surprising is that the things pointed ''to'' can be modified. But you discussed this aspect of pointer constness quite well earlier. Dereferencing a const iterator of vector yields a A* const -- the pointer is const, the pointed-to thing is not.'' -- DanMuller ---- Related to UseConstMemberFunctions. ---- CategoryLanguageFeature