mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2025-12-17 20:54:41 +03:00
Code blocks consistently use 4 spaces markdown indent (via mdast)
Exception is 8space indent for code inside bullet lists (also handled by mdast) Changes code fences as well to 4-space indent. This does not affect C++ indent within code blocks (mdast does not touch that either way).
This commit is contained in:
@@ -659,8 +659,8 @@ How do we transfer both ownership and all information needed for validating use?
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
* ???
|
* ???
|
||||||
* show how possible checks are avoided by interfaces that pass polymorphic base classes around, when they actually know what they need?
|
* show how possible checks are avoided by interfaces that pass polymorphic base classes around, when they actually know what they need?
|
||||||
Or strings as "free-style" options
|
Or strings as "free-style" options
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
@@ -1331,7 +1331,6 @@ This is a major source of errors.
|
|||||||
template <class F, class ...Args>
|
template <class F, class ...Args>
|
||||||
explicit thread(F&& f, Args&&... args); // good: throw system_error if unable to start the new thread
|
explicit thread(F&& f, Args&&... args); // good: throw system_error if unable to start the new thread
|
||||||
|
|
||||||
|
|
||||||
##### Note: What is an error?
|
##### Note: What is an error?
|
||||||
|
|
||||||
An error means that the function cannot achieve its advertised purpose (including establishing postconditions).
|
An error means that the function cannot achieve its advertised purpose (including establishing postconditions).
|
||||||
@@ -1827,6 +1826,7 @@ Consider
|
|||||||
double simpleFunc(double val, int flag1, int flag2)
|
double simpleFunc(double val, int flag1, int flag2)
|
||||||
// simpleFunc: takes a value and calculates the expected ASIC output, given the two mode flags.
|
// simpleFunc: takes a value and calculates the expected ASIC output, given the two mode flags.
|
||||||
{
|
{
|
||||||
|
|
||||||
double intermediate;
|
double intermediate;
|
||||||
if (flag1 > 0) {
|
if (flag1 > 0) {
|
||||||
intermediate = func1(val);
|
intermediate = func1(val);
|
||||||
@@ -1869,6 +1869,7 @@ We can refactor:
|
|||||||
double simpleFunc(double val, int flag1, int flag2)
|
double simpleFunc(double val, int flag1, int flag2)
|
||||||
// simpleFunc: takes a value and calculates the expected ASIC output, given the two mode flags.
|
// simpleFunc: takes a value and calculates the expected ASIC output, given the two mode flags.
|
||||||
{
|
{
|
||||||
|
|
||||||
if (flag1 > 0)
|
if (flag1 > 0)
|
||||||
return func1_muon(val, flag2);
|
return func1_muon(val, flag2);
|
||||||
if (flag1 == -1)
|
if (flag1 == -1)
|
||||||
@@ -3528,7 +3529,6 @@ The default copy operation will just copy the `p1.p` into `p2.p` leading to a do
|
|||||||
auto p2 = p1; // error: double deletion
|
auto p2 = p1; // error: double deletion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
Often the simplest way to get a destructor is to replace the pointer with a smart pointer (e.g., `std::unique_ptr`)
|
Often the simplest way to get a destructor is to replace the pointer with a smart pointer (e.g., `std::unique_ptr`)
|
||||||
@@ -4321,6 +4321,7 @@ But what if you can get significant better performance by not making a temporary
|
|||||||
T* elem;
|
T* elem;
|
||||||
int sz;
|
int sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector& Vector::operator=(const Vector& a)
|
Vector& Vector::operator=(const Vector& a)
|
||||||
@@ -5129,7 +5130,9 @@ not using this (over)general interface in favor of a particular interface found
|
|||||||
???
|
???
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
???
|
|
||||||
|
???
|
||||||
|
|
||||||
## C.hierclass: Designing classes in a hierarchy:
|
## C.hierclass: Designing classes in a hierarchy:
|
||||||
|
|
||||||
### <a name="Rh-abstract-ctor"></a> C.126: An abstract class typically doesn't need a constructor
|
### <a name="Rh-abstract-ctor"></a> C.126: An abstract class typically doesn't need a constructor
|
||||||
@@ -5408,7 +5411,7 @@ This a relatively rare use because implementation can often be organized into a
|
|||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
@@ -5821,7 +5824,7 @@ Union rule summary:
|
|||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
@@ -5858,6 +5861,7 @@ Enumeration rule summary:
|
|||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
### <a name="Renum-set"></a> Enum.2: Use enumerations to represent sets of named constants
|
### <a name="Renum-set"></a> Enum.2: Use enumerations to represent sets of named constants
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
@@ -5871,6 +5875,7 @@ Enumeration rule summary:
|
|||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
### <a name="Renum-class"></a> Enum.3: Prefer class enums over ``plain'' enums
|
### <a name="Renum-class"></a> Enum.3: Prefer class enums over ``plain'' enums
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
@@ -5912,11 +5917,12 @@ Enumeration rule summary:
|
|||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
### <a name="Renum-unnamed"></a> Enum.6: Use unnamed enumerations for ???
|
### <a name="Renum-unnamed"></a> Enum.6: Use unnamed enumerations for ???
|
||||||
|
|
||||||
##### Reason
|
##### Reason
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
@@ -5925,6 +5931,7 @@ Enumeration rule summary:
|
|||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
# <a name="S-resource"></a> R: Resource management
|
# <a name="S-resource"></a> R: Resource management
|
||||||
|
|
||||||
This section contains rules related to resources.
|
This section contains rules related to resources.
|
||||||
@@ -11461,9 +11468,9 @@ It is more likely to be stable, well-maintained, and widely available than your
|
|||||||
|
|
||||||
???
|
???
|
||||||
|
|
||||||
### SL.???: Use character-level input only when you have to; _expr.low_.
|
### SL.???: Use character-level input only when you have to; *expr.low*.
|
||||||
|
|
||||||
### SL.???: When reading, always consider ill-formed input; _expr.low_.
|
### SL.???: When reading, always consider ill-formed input; *expr.low*.
|
||||||
|
|
||||||
## SL.regex: Regex
|
## SL.regex: Regex
|
||||||
|
|
||||||
@@ -11540,47 +11547,45 @@ Reference sections:
|
|||||||
* [RS.video: Videos about "modern C++"](#SS-vid)
|
* [RS.video: Videos about "modern C++"](#SS-vid)
|
||||||
* [RF.man: Manuals](#SS-man)
|
* [RF.man: Manuals](#SS-man)
|
||||||
|
|
||||||
|
|
||||||
## <a name="SS-rules"></a> RF.rules: Coding rules
|
## <a name="SS-rules"></a> RF.rules: Coding rules
|
||||||
|
|
||||||
* [Boost Library Requirements and Guidelines](http://www.boost.org/development/requirements.html).
|
* [Boost Library Requirements and Guidelines](http://www.boost.org/development/requirements.html).
|
||||||
???.
|
???.
|
||||||
* [Bloomberg: BDE C++ Coding](https://github.com/bloomberg/bde/wiki/CodingStandards.pdf).
|
* [Bloomberg: BDE C++ Coding](https://github.com/bloomberg/bde/wiki/CodingStandards.pdf).
|
||||||
Has a strong emphasis on code organization and layout.
|
Has a strong emphasis on code organization and layout.
|
||||||
* Facebook: ???
|
* Facebook: ???
|
||||||
* [GCC Coding Conventions](https://gcc.gnu.org/codingconventions.html).
|
* [GCC Coding Conventions](https://gcc.gnu.org/codingconventions.html).
|
||||||
C++03 and (reasonably) a bit backwards looking.
|
C++03 and (reasonably) a bit backwards looking.
|
||||||
* [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html).
|
* [Google C++ Style Guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html).
|
||||||
Too timid and reflects its 1990s origins.
|
Too timid and reflects its 1990s origins.
|
||||||
[A critique from 2014](https://www.linkedin.com/pulse/20140503193653-3046051-why-google-style-guide-for-c-is-a-deal-breaker).
|
[A critique from 2014](https://www.linkedin.com/pulse/20140503193653-3046051-why-google-style-guide-for-c-is-a-deal-breaker).
|
||||||
Google are busy updating their code base and we don't know how accurately the posted guideline reflects their actual code.
|
Google are busy updating their code base and we don't know how accurately the posted guideline reflects their actual code.
|
||||||
This set of recommendations is evolving.
|
This set of recommendations is evolving.
|
||||||
* [JSF++: JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS](http://www.stroustrup.com/JSF-AV-rules.pdf).
|
* [JSF++: JOINT STRIKE FIGHTER AIR VEHICLE C++ CODING STANDARDS](http://www.stroustrup.com/JSF-AV-rules.pdf).
|
||||||
Document Number 2RDU00001 Rev C. December 2005.
|
Document Number 2RDU00001 Rev C. December 2005.
|
||||||
For flight control software.
|
For flight control software.
|
||||||
For hard real time.
|
For hard real time.
|
||||||
This means that it is necessarily very restrictive ("if the program fails somebody dies").
|
This means that it is necessarily very restrictive ("if the program fails somebody dies").
|
||||||
For example, no free store allocation or deallocation may occur after the plane takes off (no memory overflow and no fragmentation allowed).
|
For example, no free store allocation or deallocation may occur after the plane takes off (no memory overflow and no fragmentation allowed).
|
||||||
No exception may be used (because there was no available tool for guaranteeing that an exception would be handled within a fixed short time).
|
No exception may be used (because there was no available tool for guaranteeing that an exception would be handled within a fixed short time).
|
||||||
Libraries used have to have been approved for mission critical applications.
|
Libraries used have to have been approved for mission critical applications.
|
||||||
Any similarities to this set of guidelines are unsurprising because Bjarne Stroustrup was an author of JSF++.
|
Any similarities to this set of guidelines are unsurprising because Bjarne Stroustrup was an author of JSF++.
|
||||||
Recommended, but note its very specific focus.
|
Recommended, but note its very specific focus.
|
||||||
* [Mozilla Portability Guide](https://developer.mozilla.org/en-US/docs/Mozilla/C%2B%2B_Portability_Guide).
|
* [Mozilla Portability Guide](https://developer.mozilla.org/en-US/docs/Mozilla/C%2B%2B_Portability_Guide).
|
||||||
As the name indicate, this aims for portability across many (old) compilers.
|
As the name indicate, this aims for portability across many (old) compilers.
|
||||||
As such, it is restrictive.
|
As such, it is restrictive.
|
||||||
* [Geosoft.no: C++ Programming Style Guidelines](http://geosoft.no/development/cppstyle.html).
|
* [Geosoft.no: C++ Programming Style Guidelines](http://geosoft.no/development/cppstyle.html).
|
||||||
???.
|
???.
|
||||||
* [Possibility.com: C++ Coding Standard](http://www.possibility.com/Cpp/CppCodingStandard.html).
|
* [Possibility.com: C++ Coding Standard](http://www.possibility.com/Cpp/CppCodingStandard.html).
|
||||||
???.
|
???.
|
||||||
* [SEI CERT: Secure C++ Coding Standard](https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=637).
|
* [SEI CERT: Secure C++ Coding Standard](https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=637).
|
||||||
A very nicely done set of rules (with examples and rationales) done for security-sensitive code.
|
A very nicely done set of rules (with examples and rationales) done for security-sensitive code.
|
||||||
Many of their rules apply generally.
|
Many of their rules apply generally.
|
||||||
* [High Integrity C++ Coding Standard](http://www.codingstandard.com/).
|
* [High Integrity C++ Coding Standard](http://www.codingstandard.com/).
|
||||||
* [llvm](http://llvm.org/docs/CodingStandards.html).
|
* [llvm](http://llvm.org/docs/CodingStandards.html).
|
||||||
Somewhat brief, pre-C++11, and (not unreasonably) adjusted to its domain.
|
Somewhat brief, pre-C++11, and (not unreasonably) adjusted to its domain.
|
||||||
* ???
|
* ???
|
||||||
|
|
||||||
|
|
||||||
## <a name="SS-books"></a> RF.books: Books with coding guidelines
|
## <a name="SS-books"></a> RF.books: Books with coding guidelines
|
||||||
|
|
||||||
* [Meyers14](#Meyers14) Scott Meyers: Effective Modern C++ (???). Addison-Wesley 2014. Beware of overly technical and overly definite rules.
|
* [Meyers14](#Meyers14) Scott Meyers: Effective Modern C++ (???). Addison-Wesley 2014. Beware of overly technical and overly definite rules.
|
||||||
@@ -11588,16 +11593,15 @@ Somewhat brief, pre-C++11, and (not unreasonably) adjusted to its domain.
|
|||||||
* [Stroustrup05](#Stroustrup05) Bjarne Stroustrup: [A rationale for semantically enhanced library languages](http://www.stroustrup.com/SELLrationale.pdf).
|
* [Stroustrup05](#Stroustrup05) Bjarne Stroustrup: [A rationale for semantically enhanced library languages](http://www.stroustrup.com/SELLrationale.pdf).
|
||||||
LCSD05. October 2005.
|
LCSD05. October 2005.
|
||||||
* [Stroustrup14](#Stroustrup05) Stroustrup: [A Tour of C++](http://www.stroustrup.com/Tour.html).
|
* [Stroustrup14](#Stroustrup05) Stroustrup: [A Tour of C++](http://www.stroustrup.com/Tour.html).
|
||||||
Addison Wesley 2014.
|
Addison Wesley 2014.
|
||||||
Each chapter ends with an advice section consisting of a set of recommendations.
|
Each chapter ends with an advice section consisting of a set of recommendations.
|
||||||
* [Stroustrup13](#Stroustrup13) Stroustrup: [The C++ Programming Language (4th Edition)](http://www.stroustrup.com/4th.html).
|
* [Stroustrup13](#Stroustrup13) Stroustrup: [The C++ Programming Language (4th Edition)](http://www.stroustrup.com/4th.html).
|
||||||
Addison Wesley 2013.
|
Addison Wesley 2013.
|
||||||
Each chapter ends with an advice section consisting of a set of recommendations.
|
Each chapter ends with an advice section consisting of a set of recommendations.
|
||||||
* Stroustrup: [Style Guide](http://www.stroustrup.com/Programming/PPP-style.pdf)
|
* Stroustrup: [Style Guide](http://www.stroustrup.com/Programming/PPP-style.pdf)
|
||||||
for [Programming: Principles and Practice using C++](http://www.stroustrup.com/programming.html).
|
for [Programming: Principles and Practice using C++](http://www.stroustrup.com/programming.html).
|
||||||
Mostly low-level naming and layout rules.
|
Mostly low-level naming and layout rules.
|
||||||
Primarily a teaching tool.
|
Primarily a teaching tool.
|
||||||
|
|
||||||
|
|
||||||
## <a name="SS-C++"></a> RF.C++: C++ Programming (C++11/C++14)
|
## <a name="SS-C++"></a> RF.C++: C++ Programming (C++11/C++14)
|
||||||
|
|
||||||
@@ -12663,12 +12667,10 @@ No. `stack_array` is guaranteed to be allocated on the stack. Although a `std::a
|
|||||||
|
|
||||||
No. `dyn_array` is not resizable, and is a safe way to refer to a heap-allocated fixed-size array. Unlike `vector`, it is intended to replace array-`new[]`. Unlike the `dynarray` that has been proposed in the committee, this does not anticipate compiler/language magic to somehow allocate it on the stack when it is a member of an object that is allocated on the stack; it simply refers to a "dynamic" or heap-based array.
|
No. `dyn_array` is not resizable, and is a safe way to refer to a heap-allocated fixed-size array. Unlike `vector`, it is intended to replace array-`new[]`. Unlike the `dynarray` that has been proposed in the committee, this does not anticipate compiler/language magic to somehow allocate it on the stack when it is a member of an object that is allocated on the stack; it simply refers to a "dynamic" or heap-based array.
|
||||||
|
|
||||||
|
|
||||||
### <a name="Faq-gsl-expects"></a> FAQ.59: Is `Expects` the same as `assert`?
|
### <a name="Faq-gsl-expects"></a> FAQ.59: Is `Expects` the same as `assert`?
|
||||||
|
|
||||||
No. It is a placeholder for language support for contract preconditions.
|
No. It is a placeholder for language support for contract preconditions.
|
||||||
|
|
||||||
|
|
||||||
### <a name="Faq-gsl-ensures"></a> FAQ.60: Is `Ensures` the same as `assert`?
|
### <a name="Faq-gsl-ensures"></a> FAQ.60: Is `Ensures` the same as `assert`?
|
||||||
|
|
||||||
No. It is a placeholder for language support for contract postconditions.
|
No. It is a placeholder for language support for contract postconditions.
|
||||||
@@ -12744,7 +12746,6 @@ Member variables are always initialized in the order they are declared in the cl
|
|||||||
, email(first + "." + last + "@acme.com") // BAD: first and last not yet constructed
|
, email(first + "." + last + "@acme.com") // BAD: first and last not yet constructed
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
In this example, `email` will be constructed before `first` and `last` because it is declared first. That means its constructor will attempt to use `first` and `last` too soon -- not just before they are set to the desired values, but before they are constructed at all.
|
In this example, `email` will be constructed before `first` and `last` because it is declared first. That means its constructor will attempt to use `first` and `last` too soon -- not just before they are set to the desired values, but before they are constructed at all.
|
||||||
|
|
||||||
If the class definition and the constructor body are in separate files, the long-distance influence that the order of member variable declarations has over the constructor's correctness will be even harder to spot.
|
If the class definition and the constructor body are in separate files, the long-distance influence that the order of member variable declarations has over the constructor's correctness will be even harder to spot.
|
||||||
@@ -12817,36 +12818,32 @@ Should destruction behave virtually? That is, should destruction through a point
|
|||||||
|
|
||||||
The common case for a base class is that it's intended to have publicly derived classes, and so calling code is just about sure to use something like a `shared_ptr<base>`:
|
The common case for a base class is that it's intended to have publicly derived classes, and so calling code is just about sure to use something like a `shared_ptr<base>`:
|
||||||
|
|
||||||
```
|
class base {
|
||||||
class base {
|
public:
|
||||||
public:
|
|
||||||
~base(); // BAD, not virtual
|
~base(); // BAD, not virtual
|
||||||
virtual ~base(); // GOOD
|
virtual ~base(); // GOOD
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
class derived : public base { /*...*/ };
|
class derived : public base { /*...*/ };
|
||||||
|
|
||||||
{
|
{
|
||||||
shared_ptr<base> pb = make_shared<derived>();
|
shared_ptr<base> pb = make_shared<derived>();
|
||||||
// ...
|
// ...
|
||||||
} // ~pb invokes correct destructor only when ~base is virtual
|
} // ~pb invokes correct destructor only when ~base is virtual
|
||||||
```
|
|
||||||
|
|
||||||
In rarer cases, such as policy classes, the class is used as a base class for convenience, not for polymorphic behavior. It is recommended to make those destructors protected and nonvirtual:
|
In rarer cases, such as policy classes, the class is used as a base class for convenience, not for polymorphic behavior. It is recommended to make those destructors protected and nonvirtual:
|
||||||
|
|
||||||
```
|
class my_policy {
|
||||||
class my_policy {
|
public:
|
||||||
public:
|
|
||||||
virtual ~my_policy(); // BAD, public and virtual
|
virtual ~my_policy(); // BAD, public and virtual
|
||||||
protected:
|
protected:
|
||||||
~my_policy(); // GOOD
|
~my_policy(); // GOOD
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Policy>
|
template<class Policy>
|
||||||
class customizable : Policy { /*...*/ }; // note: private inheritance
|
class customizable : Policy { /*...*/ }; // note: private inheritance
|
||||||
```
|
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
@@ -12894,67 +12891,60 @@ Never allow an error to be reported from a destructor, a resource deallocation f
|
|||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
```
|
class nefarious {
|
||||||
class nefarious {
|
public:
|
||||||
public:
|
|
||||||
nefarious() { /* code that could throw */ } // ok
|
nefarious() { /* code that could throw */ } // ok
|
||||||
~nefarious() { /* code that could throw */ } // BAD, should not throw
|
~nefarious() { /* code that could throw */ } // BAD, should not throw
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
```
|
|
||||||
|
|
||||||
1. `nefarious` objects are hard to use safely even as local variables:
|
1. `nefarious` objects are hard to use safely even as local variables:
|
||||||
|
|
||||||
```
|
|
||||||
void test(string& s) {
|
void test(string& s) {
|
||||||
nefarious n; // trouble brewing
|
nefarious n; // trouble brewing
|
||||||
string copy = s; // copy the string
|
string copy = s; // copy the string
|
||||||
} // destroy copy and then n
|
} // destroy copy and then n
|
||||||
```
|
|
||||||
Here, copying `s` could throw, and if that throws and if `n`'s destructor then also throws, the program will exit via `std::terminate` because two exceptions can't be propagated simultaneously.
|
Here, copying `s` could throw, and if that throws and if `n`'s destructor then also throws, the program will exit via `std::terminate` because two exceptions can't be propagated simultaneously.
|
||||||
|
|
||||||
2. Classes with `nefarious` members or bases are also hard to use safely, because their destructors must invoke `nefarious`' destructor, and are similarly poisoned by its poor behavior:
|
2. Classes with `nefarious` members or bases are also hard to use safely, because their destructors must invoke `nefarious`' destructor, and are similarly poisoned by its poor behavior:
|
||||||
|
|
||||||
```
|
|
||||||
class innocent_bystander {
|
class innocent_bystander {
|
||||||
nefarious member; // oops, poisons the enclosing class's destructor
|
nefarious member; // oops, poisons the enclosing class's destructor
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
void test(string& s) {
|
void test(string& s) {
|
||||||
innocent_bystander i; // more trouble brewing
|
innocent_bystander i; // more trouble brewing
|
||||||
string copy = s; // copy the string
|
string copy = s; // copy the string
|
||||||
} // destroy copy and then i
|
} // destroy copy and then i
|
||||||
```
|
|
||||||
|
|
||||||
Here, if constructing `copy2` throws, we have the same problem because `i`'s destructor now also can throw, and if so we'll invoke `std::terminate`.
|
Here, if constructing `copy2` throws, we have the same problem because `i`'s destructor now also can throw, and if so we'll invoke `std::terminate`.
|
||||||
|
|
||||||
3. You can't reliably create global or static `nefarious` objects either:
|
3. You can't reliably create global or static `nefarious` objects either:
|
||||||
|
|
||||||
```
|
|
||||||
static nefarious n; // oops, any destructor exception can't be caught
|
static nefarious n; // oops, any destructor exception can't be caught
|
||||||
```
|
|
||||||
|
|
||||||
4. You can't reliably create arrays of `nefarious`:
|
4. You can't reliably create arrays of `nefarious`:
|
||||||
|
|
||||||
```
|
|
||||||
void test() {
|
void test() {
|
||||||
std::array<nefarious, 10> arr; // this line can std::terminate(!)
|
std::array<nefarious, 10> arr; // this line can std::terminate(!)
|
||||||
|
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
The behavior of arrays is undefined in the presence of destructors that throw because there is no reasonable rollback behavior that could ever be devised. Just think: What code can the compiler generate for constructing an `arr` where, if the fourth object's constructor throws, the code has to give up and in its cleanup mode tries to call the destructors of the already-constructed objects... and one or more of those destructors throws? There is no satisfactory answer.
|
The behavior of arrays is undefined in the presence of destructors that throw because there is no reasonable rollback behavior that could ever be devised. Just think: What code can the compiler generate for constructing an `arr` where, if the fourth object's constructor throws, the code has to give up and in its cleanup mode tries to call the destructors of the already-constructed objects... and one or more of those destructors throws? There is no satisfactory answer.
|
||||||
|
|
||||||
5. You can't use `Nefarious` objects in standard containers:
|
5. You can't use `Nefarious` objects in standard containers:
|
||||||
|
|
||||||
```
|
|
||||||
std::vector<nefarious> vec(10); // this is line can std::terminate()
|
std::vector<nefarious> vec(10); // this is line can std::terminate()
|
||||||
```
|
|
||||||
|
|
||||||
The standard library forbids all destructors used with it from throwing. You can't store `nefarious` objects in standard containers or use them with any other part of the standard library.
|
The standard library forbids all destructors used with it from throwing. You can't store `nefarious` objects in standard containers or use them with any other part of the standard library.
|
||||||
|
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
These are key functions that must not fail because they are necessary for the two key operations in transactional programming: to back out work if problems are encountered during processing, and to commit work if no problems occur. If there's no way to safely back out using no-fail operations, then no-fail rollback is impossible to implement. If there's no way to safely commit state changes using a no-fail operation (notably, but not limited to, `swap`), then no-fail commit is impossible to implement.
|
These are key functions that must not fail because they are necessary for the two key operations in transactional programming: to back out work if problems are encountered during processing, and to commit work if no problems occur. If there's no way to safely back out using no-fail operations, then no-fail rollback is impossible to implement. If there's no way to safely commit state changes using a no-fail operation (notably, but not limited to, `swap`), then no-fail commit is impossible to implement.
|
||||||
@@ -12968,12 +12958,10 @@ Consider the following advice and requirements found in the C++ Standard:
|
|||||||
Deallocation functions, including specifically overloaded `operator delete` and `operator delete[]`, fall into the same category, because they too are used during cleanup in general, and during exception handling in particular, to back out of partial work that needs to be undone.
|
Deallocation functions, including specifically overloaded `operator delete` and `operator delete[]`, fall into the same category, because they too are used during cleanup in general, and during exception handling in particular, to back out of partial work that needs to be undone.
|
||||||
Besides destructors and deallocation functions, common error-safety techniques rely also on `swap` operations never failing--in this case, not because they are used to implement a guaranteed rollback, but because they are used to implement a guaranteed commit. For example, here is an idiomatic implementation of `operator=` for a type `T` that performs copy construction followed by a call to a no-fail `swap`:
|
Besides destructors and deallocation functions, common error-safety techniques rely also on `swap` operations never failing--in this case, not because they are used to implement a guaranteed rollback, but because they are used to implement a guaranteed commit. For example, here is an idiomatic implementation of `operator=` for a type `T` that performs copy construction followed by a call to a no-fail `swap`:
|
||||||
|
|
||||||
```
|
T& T::operator=( const T& other ) {
|
||||||
T& T::operator=( const T& other ) {
|
|
||||||
auto temp = other;
|
auto temp = other;
|
||||||
swap(temp);
|
swap(temp);
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
(See also Item 56. ???)
|
(See also Item 56. ???)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user