mirror of
https://github.com/isocpp/CppCoreGuidelines.git
synced 2024-03-22 13:30:58 +08:00
commit
db029855dd
|
@ -3142,10 +3142,10 @@ Here on one popular implementation I got the output:
|
||||||
|
|
||||||
I expected that because the call of `g()` reuses the stack space abandoned by the call of `f()` so `*p` refers to the space now occupied by `gx`.
|
I expected that because the call of `g()` reuses the stack space abandoned by the call of `f()` so `*p` refers to the space now occupied by `gx`.
|
||||||
|
|
||||||
Imagine what would happen if `fx` and `gx` were of different types.
|
* Imagine what would happen if `fx` and `gx` were of different types.
|
||||||
Imagine what would happen if `fx` or `gx` was a type with an invariant.
|
* Imagine what would happen if `fx` or `gx` was a type with an invariant.
|
||||||
Imagine what would happen if more that dangling pointer was passed around among a larger set of functions.
|
* Imagine what would happen if more that dangling pointer was passed around among a larger set of functions.
|
||||||
Imagine what a cracker could do with that dangling pointer.
|
* Imagine what a cracker could do with that dangling pointer.
|
||||||
|
|
||||||
Fortunately, most (all?) modern compilers catch and warn against this simple case.
|
Fortunately, most (all?) modern compilers catch and warn against this simple case.
|
||||||
|
|
||||||
|
@ -3400,7 +3400,7 @@ There is not a choice when a set of functions are used to do a semantically equi
|
||||||
##### See also
|
##### See also
|
||||||
|
|
||||||
|
|
||||||
[Default arguments for virtual functions](#Rh-virtual-default-arg}
|
[Default arguments for virtual functions](#Rh-virtual-default-arg)
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
|
@ -9487,7 +9487,9 @@ For containers, there is a tradition for using `{...}` for a list of elements an
|
||||||
Initialization of a variable declared using `auto` with a single value, e.g., `{v}`, had surprising results until recently:
|
Initialization of a variable declared using `auto` with a single value, e.g., `{v}`, had surprising results until recently:
|
||||||
|
|
||||||
auto x1 {7}; // x1 is an int with the value 7
|
auto x1 {7}; // x1 is an int with the value 7
|
||||||
auto x2 = {7}; // x2 is an initializer_list<int> with an element 7 (this will will change to "element 7" in C++17)
|
// x2 is an initializer_list<int> with an element 7
|
||||||
|
// (this will will change to "element 7" in C++17)
|
||||||
|
auto x2 = {7};
|
||||||
|
|
||||||
auto x11 {7, 8}; // error: two initializers
|
auto x11 {7, 8}; // error: two initializers
|
||||||
auto x22 = {7, 8}; // x2 is an initializer_list<int> with elements 7 and 8
|
auto x22 = {7, 8}; // x2 is an initializer_list<int> with elements 7 and 8
|
||||||
|
@ -10941,10 +10943,13 @@ This makes surprises (and bugs) inevitable.
|
||||||
int a[10];
|
int a[10];
|
||||||
for (int i=0; i < 10; ++i) a[i]=i;
|
for (int i=0; i < 10; ++i) a[i]=i;
|
||||||
vector<int> v(10);
|
vector<int> v(10);
|
||||||
for (int i=0; v.size()<10; ++i) v[i]=i; // compares signed to unsigned; some compilers warn
|
// compares signed to unsigned; some compilers warn
|
||||||
|
for (int i=0; v.size() < 10; ++i) v[i]=i;
|
||||||
|
|
||||||
int a2[-2]; // error: negative size
|
int a2[-2]; // error: negative size
|
||||||
vector<int> v2(-2); // OK, but the number of ints (4294967294) is so large that we should get an exception
|
|
||||||
|
// OK, but the number of ints (4294967294) is so large that we should get an exception
|
||||||
|
vector<int> v2(-2);
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
|
@ -11200,7 +11205,10 @@ This implies added work for the programmer, is error prone, and deprives the com
|
||||||
|
|
||||||
double data[100];
|
double data[100];
|
||||||
// ... fill a ...
|
// ... fill a ...
|
||||||
qsort(data,100,sizeof(double),compare_doubles); // 100 chunks of memory of sizeof(double) starting at address data using the order defined by compare_doubles
|
|
||||||
|
// 100 chunks of memory of sizeof(double) starting at
|
||||||
|
// address data using the order defined by compare_doubles
|
||||||
|
qsort(data, 100, sizeof(double), compare_doubles);
|
||||||
|
|
||||||
From the point of view of interface design is that `qsort` throws away useful information.
|
From the point of view of interface design is that `qsort` throws away useful information.
|
||||||
|
|
||||||
|
@ -11215,7 +11223,9 @@ Here, we use the compiler's knowledge about the size of the array, the type of e
|
||||||
|
|
||||||
With C++11 plus [concepts](#???), we can do better still
|
With C++11 plus [concepts](#???), we can do better still
|
||||||
|
|
||||||
void sort(Sortable& c); // Sortable specifies that c must be a random-access sequence of elements comparable with <
|
// Sortable specifies that c must be a
|
||||||
|
// random-access sequence of elements comparable with <
|
||||||
|
void sort(Sortable& c);
|
||||||
|
|
||||||
sort(c);
|
sort(c);
|
||||||
|
|
||||||
|
@ -11224,7 +11234,8 @@ In this, the `sort` interfaces shown here still have a weakness:
|
||||||
They implicitly rely on the element type having less-than (`<`) defined.
|
They implicitly rely on the element type having less-than (`<`) defined.
|
||||||
To complete the interface, we need a second version that accepts a comparison criteria:
|
To complete the interface, we need a second version that accepts a comparison criteria:
|
||||||
|
|
||||||
void sort(Sortable& c, Predicate<Value_type<Sortable>> p); // compare elements of c using p
|
// compare elements of c using p
|
||||||
|
void sort(Sortable& c, Predicate<Value_type<Sortable>> p);
|
||||||
|
|
||||||
The standard-library specification of `sort` offers those two versions,
|
The standard-library specification of `sort` offers those two versions,
|
||||||
but the semantics is expressed in English rather than code using concepts.
|
but the semantics is expressed in English rather than code using concepts.
|
||||||
|
@ -12069,7 +12080,7 @@ A `thread` that has not been `detach()`ed when it is destroyed terminates the pr
|
||||||
|
|
||||||
##### Enforcement
|
##### Enforcement
|
||||||
|
|
||||||
* Flag `join's for `raii_thread`s ???
|
* Flag `join`s for `raii_thread`s ???
|
||||||
* Flag `detach`s for `detached_thread`s
|
* Flag `detach`s for `detached_thread`s
|
||||||
|
|
||||||
|
|
||||||
|
@ -15762,7 +15773,7 @@ Use `!=` instead of `<` to compare iterators; `!=` works for more objects becaus
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
Of course, range-for is better still where it does what you want.
|
Of course, range-`for` is better still where it does what you want.
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
|
@ -16409,7 +16420,7 @@ This slowdown can be significant compared to `printf`-style output.
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
cout << "Hello, World!" << endl; // two output operations and a flush
|
cout << "Hello, World!" << endl; // two output operations and a flush
|
||||||
cout << "hello, World!\n"; // one output operation and no flush
|
cout << "Hello, World!\n"; // one output operation and no flush
|
||||||
|
|
||||||
##### Note
|
##### Note
|
||||||
|
|
||||||
|
@ -16577,7 +16588,7 @@ Of course many simple functions will naturally have just one `return` because of
|
||||||
|
|
||||||
int index(const char* p)
|
int index(const char* p)
|
||||||
{
|
{
|
||||||
if (p==nullptr) return -1; // error indicator: alternatively `throw nullptr_error{}`
|
if (p == nullptr) return -1; // error indicator: alternatively "throw nullptr_error{}"
|
||||||
// ... do a lookup to find the index for p
|
// ... do a lookup to find the index for p
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user