C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 18:
[18.15] Why does the compiler allow me to change an int after I've pointed at it with a int const*?

Because "int const* p" means "p promises not to change the *p," not "*p promises not to change."

Causing a int const* to point to an int doesn't const-ify the int. The int can't be changed via the int const*, but if someone else has an int* (note: no const) that points to ("aliases") the same int, then that int* can be used to change the int. For example:

void f(int const* p1, int* p2)
{
  int i = *p1;         // Get the (original) value of *p1
  *p2 = 7;             // If p1 == p2, this will also change *p1
  int j = *p1;         // Get the (possibly new) value of *p1
  if (i != j) {
    std::cout << "*p1 changed, but it didn't change via pointer p1!\n";
    assert(p1 == p2);  // This is the only way *p1 could be different
  }
}

int main()
{
  int x = 5;
  f(&x, &x);           // This is perfectly legal (and even moral!)
  ...
}
Note that main() and f(int const*,int*) could be in different compilation units that are compiled on different days of the week. In that case there is no way the compiler can possibly detect the aliasing at compile time. Therefore there is no way we could make a language rule that prohibits this sort of thing. In fact, we wouldn't even want to make such a rule, since in general it's considered a feature that you can have many pointers pointing to the same thing. The fact that one of those pointers promises not to change the underlying "thing" is just a promise made by the pointer; it's not a promise made by the "thing".