Immutability is not a very fundamental notion in programming; what it means (if anything) is highly dependent on details of programming language semantics, such as argument passing conventions. Strictly speaking, there is no such thing as a mutable value: whenever one changes something, it is not the values (in the mathematical sense) themselves that change, just the question which values are contained in storage.
What is visible to the programmer is the association of expressions (including mere identifiers) to their values. In purely functional programming languages, that association once it exists can never be modified (the same expression in the same context will always continue to refer to the same value) so mutability is not a thing there. In other languages, there is usually at least the assignment of a new value to a variable that can change this association. The fact that this is possible for variables of a given type does not make the type mutable; what makes a type mutable is when the value of a variable of this type can change by something else than assignment to the variable, presumably by manipulation of the memory accessed by that variable. This applies almost exclusively to large, composite, types like arrays, strings or classes: if an integer variable resides in a register then there is no way to alter its value other than by assignment to the variable.
Often higher level languages will have an implicit pointer/reference level between the location of the variable and the value stored, in particular if the type allows values requiring vastly different amounts of storage (like unrestricted strings). Then typically assignment to the variable will be implemented by making it refer to a different memory region rather than modifying the values stored in the original memory region. Also often passing the value to a different variable (as happens in argument passing) is often implemented by just copying the reference, so original and copy are aliases for the same storage. If the language provides in addition operations that do transform the value in-place, then such operations applied to an alias will also be visible through the original variable, which then has mutable behaviour. However, if no such in-place operations are provided, then it can be ensured that in the absence of direct assignments (and of memory corruption, or cosmic rays), the value will continue to access the same value; in this case the type can be said to be immutable. This property is important in some cases, as in Python dictionaries: the integrity of the dictionary depends on the fact that no unexpected changes can occur to the key-part of its key-value pairs, so it insists that key are of an immutable type.
In C++, the user has control over everything (and the responsibility to not abuse this power), so immutability is not an issue as such. One can declare a type to be a reference of pointer to constant, which means one is protected against corrupting the corresponding memory through this reference/pointer, but if some part of the program already had non-const access to the memory, that part can still modify the memory contents, so there is no guarantee of immutability here. Classes can make it impossible for decent clients (those who refrain from const-casting and out-of-bounds writing and such) to alter storage in a way that violates their integrity, and so to effectively enforce immutability of critical values.
In interesting case of true immutability in C/C++ is function values. There is simply no way to ask for changes in function code ("please nuke the third assignment in the function body for me"). Variables of function type do not exist, but function pointers are effectively just that, if we just think of making a function pointer point to a function as "storing the function, of the proper type, in the variable". Then all assignments are in fact realised as making the variable refer to different code, not of course as moving code into the memory originally holding other code (and programmers know this, which is why the variable is called a pointer). One could apply the same method to other types, implementing all assignments as rebinding of a reference. It is conceivable to have a non functional programming language in which all values are immutable, because all assignments are implemented this way. (There are efficiency issues to be dealt with, which might explain why I cannot think of examples of such languages, but they might well exist.)