www.parashift.com/c++-faq-lite/const-correctness.html
It means using the keyword const to prevent const objects from getting mutated. For example, if you wanted to create a function f() that accepted a std::string, plus you want to promise callers not to change the caller's std::string that gets passed to f(), you can have f() receive its std::string parameter... This check is done entirely at compile-time: there is no run-time space or speed cost for the const. In the pass by value case (f3, the called function gets a copy of the caller's std::string. This means that f3() can change its local copy, but the copy is destroyed when f3() returns. In particular f3() cannot change the caller's std::string object. As an opposite example, if you wanted to create a function g() that accepted a std::string, but you want to let callers know that g() might change the caller's std::string object. In this case you can have g() receive its std::string parameter... Thus they can pass their std::string to any of the f() functions, but only f3() (the one that receives its parameter "by value") can pass its std::string to g1() or g2(). If f1() or f2() need to call either g() function, a local copy of the std::string object must be passed to the g() function; the parameter to f1() or f2() cannot be directly passed to either g() function. In particular, no changes will be made to the const parameter that was passed by reference to f1().
How is "const correctness" related to ordinary type safety? Declaring the const-ness of a parameter is just another form of type safety. If you find ordinary type safety helps you get systems correct (it does; especially in large systems), you'll find const correctness helps also.
Should I try to get things const correct "sooner" or "later"? Back-patching const correctness results in a snowball effect: every const you add "over here" requires four more to be added "over there."
non-const member function called mutate(), saying p->mutate() is an error (the error is caught by the compiler; no run-time tests are done, which means const doesn't slow your program down).
non-const member function called mutate(), saying xmutate() is an error (the error is caught by the compiler; no run-time tests are done, which means const doesn't slow your program down).
In other words, "Fred& const x" is functionally equivalent to "Fred& x". Since you're gaining nothing by adding the const after the &, you shouldn't add it since it will confuse people.
const Fred& x However, the real question is which should be used. Answer: absolutely no one should pretend they can make decisions for your organization until they know something about your organization. there is no "right" answer for all organizations, so do not allow anyone to make a knee-jerk decision in either direction. For example, some organizations value consistency and have tons of code using const Fred&; for those, Fred const& would be a bad decision independent of its merits. There are lots of other business scenarios, some of which produce a preference for Fred const&, others a preference for const Fred&. Use a style that is appropriate for your organization's average maintenance programmer. Not the gurus, not the morons, but the average maintenance programmer. Unless you're willing to fire them and hire new ones, make sure that they understand your code. Make a business decision based on your realities, not based on someone else's assumptions. You'll need to overcome a little inertia to go with Fred const&. Most current C++ books use const Fred&, most programmers learned C++ with that syntax, and most programmers still use that syntax. That doesn't mean const Fred& is necessarily better for your organization, but it does mean you may get some confusion and mistakes during the transition and/or when you integrate new people. Some organizations are convinced the benefits of Fred const& outweigh the costs;
const Fred* x However, the real question is which should be used. Answer: absolutely no one should pretend they can make decisions for your organization until they know something about your organization. there is no "right" answer for all organizations, so do not allow anyone to make a knee-jerk decision in either direction. For example, some organizations value consistency and have tons of code using const Fred*; for those, Fred const* would be a bad decision independent of its merits. There are lots of other business scenarios, some of which produce a preference for Fred const*, others a preference for const Fred*. Use a style that is appropriate for your organization's average maintenance programmer. Not the gurus, not the morons, but the average maintenance programmer. Unless you're willing to fire them and hire new ones, make sure that they understand your code. Make a business decision based on your realities, not based on someone else's assumptions. You'll need to overcome a little inertia to go with Fred const*. Most current C++ books use const Fred*, most programmers learned C++ with that syntax, and most programmers still use that syntax. That doesn't mean const Fred* is necessarily better for your organization, but it does mean you may get some confusion and mistakes during the transition and/or when you integrate new people. Some organizations are convinced the benefits of Fred const* outweigh the costs;
A member function that inspects (rather than mutates) its object. A const member function is indicated by a const suffix just after the member function's parameter list. Member functions with a const suffix are called "const member functions" or "inspectors." Member functions without a const suffix are called "non-const member functions" or "mutators." The trailing const on inspect() member function means that the abstract (client-visible) state of the object isn't going to change. This is slightly different from promising that the "raw bits" of the object's struct aren't going to change. Another (important) insight from this aliasing issue: pointing at an object with a pointer-to-const doesn't guarantee that the object won't change; it promises only that the object won't change via that pointer.
What do I do if I want a const member function to make an "invisible" change to a data member? By saying the changes are "innocuous," I mean that the changes wouldn't be visible from outside the object's interface (otherwise the member function would be a mutator rather than an inspector). When this happens, the data member which will be modified should be marked as mutable (put the mutable keyword just before the data member's declaration; This tells the compiler that the data member is allowed to change during a const member function. If your compiler doesn't support the mutable keyword, you can cast away the const'ness of this via the const_cast keyword (but see the NOTE below before doing this). Therefore you can use self to modify the object pointed to by this. NOTE: there is an extremely unlikely error that can occur with const_cast. It only happens when three very rare things are combined at the same time: a data member that ought to be mutable (such as is discussed above), a compiler that doesn't support the mutable keyword, and an object that was originally defined to be const (as opposed to a normal, non-const object that is pointed to by a pointer-to-const). Although this combination is so rare that it may never happen to you, if it ever did happen the code may not work (the Standard says the behavior is undefined). If you ever want to use const_cast, use mutable instead. In other words, if you ever need to change a member of an object, and that object is pointed to by a pointer-to-const, the safest and simplest thing to do is add mutable to the member's declaration. Please don't write and tell me that version X of compiler Y on machine Z allows you to change a non-mutable member of a const object. I don't care -- it is illegal according to the language and your code will probably fail on a different compiler or even a different version (an upgrade) of the same compiler.
This can happen only in rare cases (when the object is constructed in the scope of the const member function invocation, and when all the non-const me...
|