Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1191 replace member variable with data member #2087

Merged
merged 2 commits into from
Jan 18, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions CppCoreGuidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -4820,7 +4820,7 @@ Constructor rules:
* [C.44: Prefer default constructors to be simple and non-throwing](#Rc-default00)
* [C.45: Don't define a default constructor that only initializes data members; use member initializers instead](#Rc-default)
* [C.46: By default, declare single-argument constructors `explicit`](#Rc-explicit)
* [C.47: Define and initialize member variables in the order of member declaration](#Rc-order)
* [C.47: Define and initialize data members in the order of member declaration](#Rc-order)
* [C.48: Prefer default member initializers to member initializers in constructors for constant initializers](#Rc-in-class-initializer)
* [C.49: Prefer initialization to assignment in constructors](#Rc-initialize)
* [C.50: Use a factory function if you need "virtual behavior" during initialization](#Rc-factory)
Expand Down Expand Up @@ -5018,10 +5018,10 @@ These operations disagree about copy semantics. This will lead to confusion and

##### Enforcement

* (Complex) A copy/move constructor and the corresponding copy/move assignment operator should write to the same member variables at the same level of dereference.
* (Complex) Any member variables written in a copy/move constructor should also be initialized by all other constructors.
* (Complex) If a copy/move constructor performs a deep copy of a member variable, then the destructor should modify the member variable.
* (Complex) If a destructor is modifying a member variable, that member variable should be written in any copy/move constructors or assignment operators.
* (Complex) A copy/move constructor and the corresponding copy/move assignment operator should write to the same data members at the same level of dereference.
* (Complex) Any data members written in a copy/move constructor should also be initialized by all other constructors.
* (Complex) If a copy/move constructor performs a deep copy of a data member, then the destructor should modify the data member.
* (Complex) If a destructor is modifying a data member, that data member should be written in any copy/move constructors or assignment operators.

## <a name="SS-dtor"></a>C.dtor: Destructors

Expand Down Expand Up @@ -5144,9 +5144,9 @@ Here `p` refers to `pp` but does not own it.

##### Enforcement

* (Simple) If a class has pointer or reference member variables that are owners
* (Simple) If a class has pointer or reference members that are owners
(e.g., deemed owners by using `gsl::owner`), then they should be referenced in its destructor.
* (Hard) Determine if pointer or reference member variables are owners when there is no explicit statement of ownership
* (Hard) Determine if pointer or reference members are owners when there is no explicit statement of ownership
(e.g., look into the constructors).

### <a name="Rc-dtor-ptr"></a>C.32: If a class has a raw pointer (`T*`) or reference (`T&`), consider whether it might be owning
Expand Down Expand Up @@ -5491,7 +5491,7 @@ If a valid object cannot conveniently be constructed by a constructor, [use a fa

##### Enforcement

* (Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
* (Simple) Every constructor should initialize every data member (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
Expand Down Expand Up @@ -5784,7 +5784,7 @@ Using default member initializers lets the compiler generate the function for yo

##### Enforcement

(Simple) A default constructor should do more than just initialize member variables with constants.
(Simple) A default constructor should do more than just initialize data members with constants.

### <a name="Rc-explicit"></a>C.46: By default, declare single-argument constructors explicit

Expand Down Expand Up @@ -5824,7 +5824,7 @@ Copy and move constructors should not be made `explicit` because they do not per

(Simple) Single-argument constructors should be declared `explicit`. Good single argument non-`explicit` constructors are rare in most code bases. Warn for all that are not on a "positive list".

### <a name="Rc-order"></a>C.47: Define and initialize member variables in the order of member declaration
### <a name="Rc-order"></a>C.47: Define and initialize data members in the order of member declaration

##### Reason

Expand Down Expand Up @@ -5894,7 +5894,7 @@ How would a maintainer know whether `j` was deliberately uninitialized (probably

##### Enforcement

* (Simple) Every constructor should initialize every member variable (either explicitly, via a delegating ctor call or via default construction).
* (Simple) Every constructor should initialize every data member (either explicitly, via a delegating ctor call or via default construction).
* (Simple) Default arguments to constructors suggest a default member initializer might be more appropriate.

### <a name="Rc-initialize"></a>C.49: Prefer initialization to assignment in constructors
Expand Down Expand Up @@ -7719,7 +7719,7 @@ Consider making such a class a `struct` -- that is, a behaviorless bunch of vari
int y {0};
};

Note that we can put default initializers on member variables: [C.49: Prefer initialization to assignment in constructors](#Rc-initialize).
Note that we can put default initializers on data members: [C.49: Prefer initialization to assignment in constructors](#Rc-initialize).

##### Note

Expand Down Expand Up @@ -10918,7 +10918,7 @@ Many such errors are introduced during maintenance years after the initial imple

##### Example

This rule covers member variables.
This rule covers data members.

class X {
public:
Expand Down Expand Up @@ -14554,7 +14554,7 @@ but we can mention:
and some older versions of [GCC](https://gcc.gnu.org/wiki/ThreadSafetyAnnotation)
have some support for static annotation of thread safety properties.
Consistent use of this technique turns many classes of thread-safety errors into compile-time errors.
The annotations are generally local (marking a particular member variable as guarded by a particular mutex),
The annotations are generally local (marking a particular data member as guarded by a particular mutex),
and are usually easy to learn. However, as with many static tools, it can often present false negatives;
cases that should have been caught but were allowed.

Expand Down Expand Up @@ -15784,7 +15784,7 @@ Sometimes C++ code allocates the `volatile` memory and shares it with "elsewhere
##### Example, bad

`volatile` local variables are nearly always wrong -- how can they be shared with other languages or hardware if they're ephemeral?
The same applies almost as strongly to member variables, for the same reason.
The same applies almost as strongly to data members, for the same reason.

void f()
{
Expand All @@ -15793,7 +15793,7 @@ The same applies almost as strongly to member variables, for the same reason.
}

class My_type {
volatile int i = 0; // suspicious, volatile member variable
volatile int i = 0; // suspicious, volatile data member
// etc.
};

Expand All @@ -15803,7 +15803,7 @@ In C++, unlike in some other languages, `volatile` has [nothing to do with synch

##### Enforcement

* Flag `volatile T` local and member variables; almost certainly you intended to use `atomic<T>` instead.
* Flag `volatile T` local and data members; almost certainly you intended to use `atomic<T>` instead.
* ???

### <a name="Rconc-signal"></a>CP.201: ??? Signals
Expand Down Expand Up @@ -16959,7 +16959,7 @@ it offers to its users.

##### Enforcement

* Flag a member function that is not marked `const`, but that does not perform a non-`const` operation on any member variable.
* Flag a member function that is not marked `const`, but that does not perform a non-`const` operation on any data member.

### <a name="Rconst-ref"></a>Con.3: By default, pass pointers and references to `const`s

Expand Down Expand Up @@ -21181,7 +21181,7 @@ Type safety profile summary:
Prefer [construction](#Res-construct) or [named casts](#Res-casts-named) or `T{expression}`.
* <a name="Pro-type-init"></a>Type.5: Don't use a variable before it has been initialized:
[always initialize](#Res-always).
* <a name="Pro-type-memberinit"></a>Type.6: Always initialize a member variable:
* <a name="Pro-type-memberinit"></a>Type.6: Always initialize a data member:
[always initialize](#Res-always),
possibly using [default constructors](#Rc-default0) or
[default member initializers](#Rc-in-class-initializer).
Expand Down Expand Up @@ -22244,9 +22244,9 @@ Modernization can be much faster, simpler, and safer when supported with analysi
This section contains follow-up material on rules and sets of rules.
In particular, here we present further rationale, longer examples, and discussions of alternatives.

### <a name="Sd-order"></a>Discussion: Define and initialize member variables in the order of member declaration
### <a name="Sd-order"></a>Discussion: Define and initialize data members in the order of member declaration

Member variables are always initialized in the order they are declared in the class definition, so write them in that order in the constructor initialization list. Writing them in a different order just makes the code confusing because it won't run in the order you see, and that can make it hard to see order-dependent bugs.
Data members are always initialized in the order they are declared in the class definition, so write them in that order in the constructor initialization list. Writing them in a different order just makes the code confusing because it won't run in the order you see, and that can make it hard to see order-dependent bugs.

class Employee {
string email, first, last;
Expand All @@ -22264,7 +22264,7 @@ Member variables are always initialized in the order they are declared in the cl

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 data member declarations has over the constructor's correctness will be even harder to spot.

**References**:

Expand Down Expand Up @@ -22988,7 +22988,7 @@ Alternatively, we will decide that no change is needed and delete the entry.
* Should there be inline namespaces (à la `std::literals::*_literals`)?
* Avoid implicit conversions
* Const member functions should be thread safe ... aka, but I don't really change the variable, just assign it a value the first time it's called ... argh
* Always initialize variables, use initialization lists for member variables.
* Always initialize variables, use initialization lists for data members.
* Anyone writing a public interface which takes or returns `void*` should have their toes set on fire. That one has been a personal favorite of mine for a number of years. :)
* Use `const`-ness wherever possible: member functions, variables and (yippee) `const_iterators`
* Use `auto`
Expand Down