Use const identifiers by default. They provide guarantees for the reader/maintainer, and are way easier to build in than to insert afterwards.
Both member variables and methods would be declared const, as well as function arguments. const member variables enforce proper use of the initializer list.
A side-effect of this rule: avoid methods with side-effects.
------ EDIT
const member variables seemed like a good idea; this is not always the case: they effectively make any object immutable. This becomes problematic for e.g. sorting a vector.
struct A {
const int i;
};
bool operator<(const A& lhs, const A& rhs) {
return lhs.i < rhs.i;
}
int main() {
std::vector<A> as;
as.emplace_back(A{1});
std::sort(begin(as), end(as));
}
error message:
... note: copy assignment operator of 'A' is implicitly deleted because
field 'i' is of const-qualified type 'const int'
...
in instantiation of function template specialization 'std::sort<...>'
requested here
std::sort(begin(as), end(as));