mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
immutability
Added immutability under "Philosophy" and fleshed out the Con section
This commit is contained in:
parent
f1fcc0fe68
commit
dfd29f3963
|
@ -343,6 +343,7 @@ Philosophy rules summary:
|
||||||
* [P.7: Catch run-time errors early](#Rp-early)
|
* [P.7: Catch run-time errors early](#Rp-early)
|
||||||
* [P.8: Don't leak any resources](#Rp-leak)
|
* [P.8: Don't leak any resources](#Rp-leak)
|
||||||
* [P.9: Don't waste time or space](#Rp-waste)
|
* [P.9: Don't waste time or space](#Rp-waste)
|
||||||
|
* [P.10: Prefer immutable data to mutable data](#Rp-mutable)
|
||||||
|
|
||||||
Philosophical rules are generally not mechanically checkable.
|
Philosophical rules are generally not mechanically checkable.
|
||||||
However, individual rules reflecting these philosophical themes are.
|
However, individual rules reflecting these philosophical themes are.
|
||||||
|
@ -928,6 +929,19 @@ After that, we can look at waste related to algorithms and requirements, but tha
|
||||||
|
|
||||||
Many more specific rules aim at the overall goals of simplicity and elimination of gratuitous waste.
|
Many more specific rules aim at the overall goals of simplicity and elimination of gratuitous waste.
|
||||||
|
|
||||||
|
### <a name="Rp-mutable"></a>P.10: Prefer immutable data to mutable data
|
||||||
|
|
||||||
|
##### Reason
|
||||||
|
|
||||||
|
It is easier to reason about constants than about variables.
|
||||||
|
Sumething immutable cannot change unexpectedly.
|
||||||
|
Sometimes immutability enables better optimization.
|
||||||
|
You can't have a data race on a constant.
|
||||||
|
|
||||||
|
See [Con: Constants and Immutability](#S-const)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# <a name="S-interfaces"></a>I: Interfaces
|
# <a name="S-interfaces"></a>I: Interfaces
|
||||||
|
|
||||||
An interface is a contract between two parts of a program. Precisely stating what is expected of a supplier of a service and a user of that service is essential.
|
An interface is a contract between two parts of a program. Precisely stating what is expected of a supplier of a service and a user of that service is essential.
|
||||||
|
@ -10715,16 +10729,29 @@ Constant rule summary:
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
Immutable objects are easier to reason about, so make object non-`const` only when there is a need to change their value.
|
Immutable objects are easier to reason about, so make object non-`const` only when there is a need to change their value.
|
||||||
|
Prevents accidental or hard-to-notice change of value.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
for (
|
for (const string& s : c) cout << s << '\n'; // just reading: const
|
||||||
container
|
|
||||||
???
|
for (string& s : c) cout << s << '\n'; // BAD: just reading
|
||||||
|
|
||||||
|
for (string& s: c) cin>>s; // needs to write: non-const
|
||||||
|
|
||||||
|
##### Exception
|
||||||
|
|
||||||
|
Function arguments are rarely mutated, but also rarely declared const.
|
||||||
|
To avoid confusion and lots of false positives, don't enforce this rule for function arguments.
|
||||||
|
|
||||||
|
void f(const char*const p); // pedantic
|
||||||
|
void g(const int i); // pedantic
|
||||||
|
|
||||||
|
Note that function parameter is a local variable so changes to it are local.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* Flag non-const variables that are not modified (except for parameters to avoid many false positives)
|
||||||
|
|
||||||
### <a name="Rconst-fct"></a>Con.2: By default, make member functions `const`
|
### <a name="Rconst-fct"></a>Con.2: By default, make member functions `const`
|
||||||
|
|
||||||
|
@ -10759,39 +10786,64 @@ This gives a more precise statement of design intent, better readability, more e
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
To avoid a called function unexpectedly changing the value.
|
||||||
|
It's far easier to reason about programs when called functions don't modify state.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
???
|
void f(char* p); // does f modify *p? (assume it does)
|
||||||
|
void g(const char* p); // g does not modify *p
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
It is not inherently bad to pass a pointer or reference to non-const,
|
||||||
|
but that should be done only when the called function is supposed to modify the object.
|
||||||
|
|
||||||
|
##### Note
|
||||||
|
|
||||||
|
[Do not cast away `const`](#Res-casts-const).
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* flag function that does not modify an object passed by pointer or reference to non-cost
|
||||||
|
* flag a function that (using a cast) modifies an object passed by pointer or reference to const
|
||||||
|
|
||||||
### <a name="Rconst-const"></a>Con.4: Use `const` to define objects with values that do not change after construction
|
### <a name="Rconst-const"></a>Con.4: Use `const` to define objects with values that do not change after construction
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
Prevent surprises from unexpectedly changed object values.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
???
|
void f()
|
||||||
|
{
|
||||||
|
int x = 7;
|
||||||
|
const int y = 9;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
As `x` is not const, we must assume that it is modified somewhere in the loop.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* Flag unmodified non-const variables.
|
||||||
|
|
||||||
### <a name="Rconst-constexpr"></a>Con.5: Use `constexpr` for values that can be computed at compile time
|
### <a name="Rconst-constexpr"></a>Con.5: Use `constexpr` for values that can be computed at compile time
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
Better performance, better compile-time checking, guaranteed compile-time evaluation, no possibility of race conditions.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
???
|
double x = f(2); // possible run-time evaluation
|
||||||
|
const double x = f(2); // possible run-time evaluation
|
||||||
|
constexpr double y = f(2); // error unless f(2) can be evaluated at compile time
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
|
@ -10799,7 +10851,7 @@ See F.4.
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
* Flag `const` definitions with constant expression initializers.
|
||||||
|
|
||||||
# <a name="S-templates"></a>T: Templates and generic programming
|
# <a name="S-templates"></a>T: Templates and generic programming
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user