Updating gh-pages

This commit is contained in:
Andrew Pardoe
2016-12-12 11:41:31 -08:00
parent 02afdc0bcb
commit 980d3fa8c9

View File

@@ -4,7 +4,7 @@ layout: default
# <a name="main"></a>C++ Core Guidelines
November 21, 2016
December 12, 2016
Editors:
@@ -2825,7 +2825,7 @@ In traditional C and C++ code, plain `T*` is used for many weakly-related purpos
* Identify an array with a length specified separately
* Identify a location in an array
The makes it hard to understand what code does and is supposed to do.
This makes it hard to understand what the code does and is supposed to do.
It complicates checking and tool support.
##### Example
@@ -4548,6 +4548,11 @@ Compilers do not read comments.
If a valid object cannot conveniently be constructed by a constructor, [use a factory function](#Rc-factory).
##### Enforcement
* (Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
* (Unknown) If a constructor has an `Ensures` contract, try to see if it holds as a postcondition.
##### Note
If a constructor acquires a resource (to create a valid object), that resource should be [released by the destructor](#Rc-dtor-release).
@@ -4638,9 +4643,6 @@ Another reason is been to delay initialization until an object is needed; the so
##### Enforcement
* (Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
* (Unknown) If a constructor has an `Ensures` contract, try to see if it holds as a postcondition.
### <a name="Rc-default0"></a>C.43: Ensure that a class has a default constructor
##### Reason
@@ -5898,7 +5900,7 @@ Designing rules for classes in a hierarchy summary:
* [C.126: An abstract class typically doesn't need a constructor](#Rh-abstract-ctor)
* [C.127: A class with a virtual function should have a virtual or protected destructor](#Rh-dtor)
* [C.128: Use `override` to make overriding explicit in large class hierarchies](#Rh-override)
* [C.128: Virtual functions should specify exactly one of `virtual`, `override`, or `final`](#Rh-override)
* [C.129: When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance](#Rh-kind)
* [C.130: Redefine or prohibit copying for a base class; prefer a virtual `clone` function instead](#Rh-copy)
* [C.131: Avoid trivial getters and setters](#Rh-get)
@@ -8480,8 +8482,9 @@ A function that does not manipulate lifetime should take raw pointers or referen
##### Enforcement
* (Simple) Warn if a function takes a parameter of a smart pointer type (that overloads `operator->` or `operator*`) `unique_ptr` or `shared_ptr` and the function only calls any of: `operator*`, `operator->` or `get()`.
* Flag a parameter of a smart pointer type (a type that overloads `operator->` or `operator*`) that is copyable but never copied/moved from in the function body or else movable but never moved from in the function body or by being a by-value parameter, and that is never modified, and that is not passed along to another function that could do so. That means the ownership semantics are not used.
* (Simple) Warn if a function takes a parameter of a smart pointer type (that overloads `operator->` or `operator*`) that is copyable but the function only calls any of: `operator*`, `operator->` or `get()`.
Suggest using a `T*` or `T&` instead.
* Flag a parameter of a smart pointer type (a type that overloads `operator->` or `operator*`) that is copyable/movable but never copied/moved from in the function body, and that is never modified, and that is not passed along to another function that could do so. That means the ownership semantics are not used.
Suggest using a `T*` or `T&` instead.
### <a name="Rr-smart"></a>R.31: If you have non-`std` smart pointers, follow the basic pattern from `std`
@@ -8740,7 +8743,7 @@ Expression rules:
* [ES.55: Avoid the need for range checking](#Res-range-checking)
* [ES.56: Avoid `std::move()` in application code](#Res-move)
* [ES.60: Avoid `new` and `delete` outside resource management functions](#Res-new)
* [ES.61: delete arrays using `delete[]` and non-arrays using `delete`](#Res-del)
* [ES.61: Delete arrays using `delete[]` and non-arrays using `delete`](#Res-del)
* [ES.62: Don't compare pointers into different arrays](#Res-arr2)
* [ES.63: Don't slice](#Res-slice)
@@ -8750,7 +8753,7 @@ Statement rules:
* [ES.71: Prefer a range-`for`-statement to a `for`-statement when there is a choice](#Res-for-range)
* [ES.72: Prefer a `for`-statement to a `while`-statement when there is an obvious loop variable](#Res-for-while)
* [ES.73: Prefer a `while`-statement to a `for`-statement when there is no obvious loop variable](#Res-while-for)
* [ES.74: Prefer to declare a loop variable in the initializer part of as `for`-statement](#Res-for-init)
* [ES.74: Prefer to declare a loop variable in the initializer part of a `for`-statement](#Res-for-init)
* [ES.75: Avoid `do`-statements](#Res-do)
* [ES.76: Avoid `goto`](#Res-goto)
* [ES.77: ??? `continue`](#Res-continue)
@@ -8838,7 +8841,7 @@ Not easy. ??? Look for messy loops, nested loops, long functions, absence of fun
## ES.dcl: Declarations
A declaration is a statement. a declaration introduces a name into a scope and may cause the construction of a named object.
A declaration is a statement. A declaration introduces a name into a scope and may cause the construction of a named object.
### <a name="Res-scope"></a>ES.5: Keep scopes small
@@ -9537,7 +9540,7 @@ Initialization of a variable declared using `auto` with a single value, e.g., `{
Use `={...}` if you really want an `initializer_list<T>`
auto fib10 = {0, 1, 2, 3, 5, 8, 13, 25, 38, 63}; // fib10 is a list
auto fib10 = {0, 1, 2, 3, 5, 8, 13, 21, 34, 55}; // fib10 is a list
##### Note
@@ -9590,7 +9593,7 @@ If `leak == true` the object pointed to by `p2` is leaked and the object pointed
Look for raw pointers that are targets of `new`, `malloc()`, or functions that may return such pointers.
### <a name="Res-const"></a>ES.25: Declare objects `const` or `constexpr` unless you want to modify its value later on
### <a name="Res-const"></a>ES.25: Declare an object `const` or `constexpr` unless you want to modify its value later on
##### Reason
@@ -9729,8 +9732,8 @@ Hard. At best a heuristic. Look for an uninitialized variable followed by a loop
Macros are a major source of bugs.
Macros don't obey the usual scope and type rules.
Macros ensure that the human reader see something different from what the compiler sees.
Macros complicates tool building.
Macros ensure that the human reader sees something different from what the compiler sees.
Macros complicate tool building.
##### Example, bad
@@ -9744,7 +9747,7 @@ This rule does not ban the use of macros for "configuration control" use in `#if
##### Enforcement
Scream when you see a macro that isn't just use for source control (e.g., `#ifdef`)
Scream when you see a macro that isn't just used for source control (e.g., `#ifdef`)
### <a name="Res-macros2"></a>ES.31: Don't use macros for constants or "functions"
@@ -9869,7 +9872,7 @@ Statements control the flow of control (except for function calls and exception
* Readability.
* Efficiency: A `switch` compares against constants and is usually better optimized than a series of tests in an `if`-`then`-`else` chain.
* a `switch` is enables some heuristic consistency checking. For example, have all values of an `enum` been covered? If not, is there a `default`?
* A `switch` enables some heuristic consistency checking. For example, have all values of an `enum` been covered? If not, is there a `default`?
##### Example
@@ -9919,8 +9922,8 @@ Readability. Error prevention. Efficiency.
cout << f(v, &v[i]) << '\n';
for (int i = 0; i < v.size(); ++i) { // body messes with loop variable: can't be a range-for
if (i % 2)
++i; // skip even elements
if (i % 2 == 0)
continue; // skip even elements
else
cout << v[i] << '\n';
}
@@ -9985,7 +9988,7 @@ Readability: the complete logic of the loop is visible "up front". The scope of
???
### <a name="Res-for-init"></a>ES.74: Prefer to declare a loop variable in the initializer part of as `for`-statement
### <a name="Res-for-init"></a>ES.74: Prefer to declare a loop variable in the initializer part of a `for`-statement
##### Reason
@@ -10222,10 +10225,10 @@ Complicated expressions are error-prone.
// better, but possibly still too complicated
for (char c1, c2; cin >> c1 >> c2 && c1 == c2;)
// OK: iff i and j are not aliased
// OK: if i and j are not aliased
int x = ++i + ++j;
// OK: iff i != j and i != k
// OK: if i != j and i != k
v[i] = v[j] + v[k];
// bad: multiple assignments "hidden" in subexpressions
@@ -10796,7 +10799,7 @@ There can be code in the `...` part that causes the `delete` never to happen.
Flag naked `new`s and naked `delete`s.
### <a name="Res-del"></a>ES.61: delete arrays using `delete[]` and non-arrays using `delete`
### <a name="Res-del"></a>ES.61: Delete arrays using `delete[]` and non-arrays using `delete`
##### Reason
@@ -10865,7 +10868,7 @@ The first defense against this is to [define the base class `Shape` not to allow
##### Alternative
If you mean to slice, define an explicit operations to do so.
If you mean to slice, define an explicit operation to do so.
This saves readers from confusion.
For example:
@@ -10965,7 +10968,7 @@ This is even more true for mixed signed and unsigned arithmetic.
}
Here we have been very explicit about what's happening,
but if you had see `us-(s+2)` or `s+=2; ... us-s` would you reliably have suspected that the result would print as `4294967294`?
but if you had seen `us-(s+2)` or `s+=2; ... us-s`, would you reliably have suspected that the result would print as `4294967294`?
##### Exception
@@ -11505,7 +11508,7 @@ Concurrency and parallelism rule summary:
* [CP.2: Avoid data races](#Rconc-races)
* [CP.3: Minimize explicit sharing of writable data](#Rconc-data)
* [CP.4: Think in terms of tasks, rather than threads](#Rconc-task)
* [CP.8 Don't try to use `volatile` for synchronization](#Rconc-volatile)
* [CP.8: Don't try to use `volatile` for synchronization](#Rconc-volatile)
See also:
@@ -11715,7 +11718,7 @@ This is a potent argument for using higher level, more applications-oriented lib
???
### <a name="Rconc-volatile"></a>CP.8 Don't try to use `volatile` for synchronization
### <a name="Rconc-volatile"></a>CP.8: Don't try to use `volatile` for synchronization
##### Reason
@@ -11787,7 +11790,7 @@ Concurrency rule summary:
* [CP.26: Prefer `gsl::detached_thread` over `std::thread` if you plan to `detach()`](#Rconc-detached_thread)
* [CP.27: Use plain `std::thread` for `thread`s that detach based on a run-time condition (only)](#Rconc-thread)
* [CP.28: Remember to join scoped `thread`s that are not `detach()`ed](#Rconc-join-undetached)
* [CP.30: Do not pass pointers to local variables to non-`raii_thread's](#Rconc-pass)
* [CP.30: Do not pass pointers to local variables to non-`raii_thread`s](#Rconc-pass)
* [CP.31: Pass small amounts of data between threads by value, rather than by reference or pointer](#Rconc-data-by-value)
* [CP.32: To share ownership between unrelated `thread`s use `shared_ptr`](#Rconc-shared)
* [CP.40: Minimize context switching](#Rconc-switch)
@@ -12126,7 +12129,7 @@ A `thread` that has not been `detach()`ed when it is destroyed terminates the pr
* Flag `detach`s for `detached_thread`s
### <a name="RRconc-pass"></a>CP.30: Do not pass pointers to local variables to non-`raii_thread's
### <a name="RRconc-pass"></a>CP.30: Do not pass pointers to local variables to non-`raii_thread`s
##### Reason
@@ -12596,7 +12599,7 @@ If you are doing lock-free programming for performance, you need to check for re
Instruction reordering (static and dynamic) makes it hard for us to think effectively at this level (especially if you use relaxed memory models).
Experience, (semi)formal models and model checking can be useful.
Testing - often to an extreme extent - is essential.
"Don't fly too close to the wind."
"Don't fly too close to the sun."
##### Enforcement
@@ -12864,7 +12867,7 @@ If `use()` could handle the failure to construct `bar` it can take control using
In either case, `Foo`'s constructor correctly destroys constructed members before passing control to whatever tried to create a `Foo`.
Note that there is no return value that could contain an error code.
The `File_handle` constructor might defined like this:
The `File_handle` constructor might be defined like this:
File_handle::File_handle(const string& name, const string& mode)
:f{fopen(name.c_str(), mode.c_str())}
@@ -13439,9 +13442,9 @@ In the absence of appropriate time estimation tools, this is hard to guarantee f
Such systems (e.g. flight control software) typically also ban the use of dynamic (heap) memory.
So, the primary guideline for error handling is "use exceptions and [RAII](#Re-raii)."
This section deals with the cases where you either do not have an efficient implementation or exceptions
This section deals with the cases where you either do not have an efficient implementation of exceptions,
or have such a rat's nest of old-style code
(e.g., lots of pointers, ill-defined ownership, and lots of unsystematic error handling based on tests of errors codes)
(e.g., lots of pointers, ill-defined ownership, and lots of unsystematic error handling based on tests of error codes)
that it is infeasible to introduce simple and systematic exception handling.
Before condemning exceptions or complaining too much about their cost, consider examples of the use of [error codes](#Re-no-throw-codes).
@@ -13469,7 +13472,7 @@ If we cannot throw an exception, we can simulate this RAII style of resource han
return 0; // zero indicates "good"
}
The problem is of course that the caller now have to remember to test the return value.
The problem is of course that the caller now has to remember to test the return value.
**See also**: [Discussion](#Sd-???).
@@ -13717,7 +13720,7 @@ Constant rule summary:
##### 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 objects non-`const` only when there is a need to change their value.
Prevents accidental or hard-to-notice change of value.
##### Example
@@ -15117,7 +15120,7 @@ This limits use and typically increases code size.
// ...
private:
Node* head;
Link* head;
};
List<int> lst1;
@@ -15144,7 +15147,7 @@ This looks innocent enough, but ???
// ...
private:
Node* head;
Link* head;
};
List<int> lst1;
@@ -15456,12 +15459,12 @@ Note that `maul()` violates the a `T*` points to an individual object [Rule](#??
*p = Pear{}; // put a Pear into *p
}
vector<Apple> va = { an_apple, another_apple }; // aa contains Apples (obviously!)
vector<Apple> va = { an_apple, another_apple }; // va contains Apples (obviously!)
maul2(aa); // error: cannot convert a vector<Apple> to a Fruit*
maul2(&aa[0]); // you asked for it
maul2(va); // error: cannot convert a vector<Apple> to a Fruit*
maul2(&va[0]); // you asked for it
Apple& a0 = &aa[0]; // a Pear?
Apple& a0 = &va[0]; // a Pear?
Note that the assignment in `maul2()` violated the no-slicing [Rule](#???).
@@ -15551,7 +15554,7 @@ It could be a base class:
List<string> ls;
Now there is only one copy of the operations linking and unlinking elements of a `List`.
The `Link` and `List` classes does nothing but type manipulation.
The `Link` and `List` classes do nothing but type manipulation.
Instead of using a separate "base" type, another common technique is to specialize for `void` or `void*` and have the general template for `T` be just the safely-encapsulated casts to and from the core `void` implementation.
@@ -16624,7 +16627,7 @@ The positive arguments for alternatives to these non-rules are listed in the rul
Non-rule summary:
* [NR.1: Don't: All declarations should be at the top of a function](#Rnr-top)
* [NR.2: Don't: Have only a single single `return`-statement in a function](#Rnr-single-return)
* [NR.2: Don't: Have only a single `return`-statement in a function](#Rnr-single-return)
* [NR.3: Don't: Don't use exceptions](#Rnr-no-exceptions)
* [NR.4: Don't: Place each class declaration in its own source file](#Rnr-lots-of-files)
* [NR.5: Don't: Don't do substantive work in a constructor; instead use two-phase initialization](#Rnr-two-phase-init)
@@ -16652,7 +16655,7 @@ Fortunately, compilers catch many "used before set" errors.
* [Always initialize an object](#Res-always)
* [ES.21: Don't introduce a variable (or constant) before you need to use it](#Res-introduce)
### <a name="Rnr-single-return"></a>NR.2: Don't: Have only a single single `return`-statement in a function
### <a name="Rnr-single-return"></a>NR.2: Don't: Have only a single `return`-statement in a function
##### Reason (not to follow this rule)
@@ -17742,14 +17745,14 @@ IDEs and tools can help (as well as hinder).
Naming and layout rules:
* [NL 1: Don't say in comments what can be clearly stated in code](#Rl-comments)
* [NL.1: Don't say in comments what can be clearly stated in code](#Rl-comments)
* [NL.2: State intent in comments](#Rl-comments-intent)
* [NL.3: Keep comments crisp](#Rl-comments-crisp)
* [NL.4: Maintain a consistent indentation style](#Rl-indent)
* [NL.5: Don't encode type information in names](#Rl-name-type)
* [NL.7: Make the length of a name roughly proportional to the length of its scope](#Rl-name-length)
* [NL.8: Use a consistent naming style](#Rl-name)
* [NL 9: Use `ALL_CAPS` for macro names only](#Rl-all-caps)
* [NL.9: Use `ALL_CAPS` for macro names only](#Rl-all-caps)
* [NL.10: Avoid CamelCase](#Rl-camel)
* [NL.15: Use spaces sparingly](#Rl-space)
* [NL.16: Use a conventional class member declaration order](#Rl-order)
@@ -17856,7 +17859,7 @@ Use a tool.
##### Rationale
If names reflects type rather than functionality, it becomes hard to change the types used to provide that functionality.
If names reflect types rather than functionality, it becomes hard to change the types used to provide that functionality.
Also, if the type of a variable is changed, code using it will have to be modified.
Minimize unintentional conversions.
@@ -17931,7 +17934,7 @@ The use of `p` for pointer and `x` for a floating-point variable is conventional
##### Note
Where are many styles and when you use multiple libraries, you can't follow all their differences conventions.
There are many styles and when you use multiple libraries, you can't follow all their different conventions.
Choose a "house style", but leave "imported" libraries with their original style.
##### Example
@@ -17975,11 +17978,11 @@ Try to be consistent in your use of acronyms and lengths of identifiers:
Would be possible except for the use of libraries with varying conventions.
### <a name="Rl-all-caps"></a>NL 9: Use `ALL_CAPS` for macro names only
### <a name="Rl-all-caps"></a>NL.9: Use `ALL_CAPS` for macro names only
##### Reason
To avoid confusing macros from names that obeys scope and type rules.
To avoid confusing macros with names that obey scope and type rules.
##### Example
@@ -18188,7 +18191,7 @@ Impossible in the face of history.
##### Reason
Readability.
Not everyone has screens and printers that makes it easy to distinguish all characters.
Not everyone has screens and printers that make it easy to distinguish all characters.
We easily confuse similarly spelled and slightly misspelled words.
##### Example
@@ -18877,7 +18880,7 @@ To avoid extremely hard-to-find errors. Dereferencing such a pointer is undefine
string* bad() // really bad
{
vector<string> v = { "this", "will", "cause" "trouble" };
vector<string> v = { "This", "will", "cause", "trouble", "!" };
// leaking a pointer into a destroyed member of a destroyed object (v)
return &v[0];
}
@@ -18886,7 +18889,7 @@ To avoid extremely hard-to-find errors. Dereferencing such a pointer is undefine
{
string* p = bad();
vector<int> xx = {7, 8, 9};
// undefined behavior: x may not be "this"
// undefined behavior: x may not be the string "This"
string x = *p;
// undefined behavior: we don't know what (if anything) is allocated a location p
*p = "Evil!";