C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 18:
[18.1] What is "const correctness"?

A good thing. 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...

  • void f1(std::string const& s); // Pass by reference-to-const
  • void f2(std::string const* sptr); // Pass by pointer-to-const
  • void f3(std::string s); // Pass by value

In the pass by reference-to-const and pass by pointer-to-const cases, any attempts to change the caller's std::string within the f() functions would be flagged by the compiler as an error at compile-time. 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, suppose 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...

  • void g1(std::string& s); // Pass by reference-to-non-const
  • void g2(std::string* sptr); // Pass by pointer-to-non-const

The lack of const in these functions tells the compiler that they are allowed to (but are not required to) change the caller's std::string object. 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. E.g.,

void g1(std::string& s);

void f1(std::string const& s)
{
  g1(s);          // Compile-time Error since s is const

  std::string localCopy = s;
  g1(localCopy);  // OK since localCopy is not const
}
Naturally in the above case, any changes that g1() makes are made to the localCopy object that is local to f1(). In particular, no changes will be made to the const parameter that was passed by reference to f1().