From 41426a1a5fce2cb356b7fc2d9aee69e46980541b Mon Sep 17 00:00:00 2001 From: Jan Schultke Date: Thu, 18 Jan 2024 22:20:40 +0100 Subject: [PATCH] #1191 replace member variable with data member (#2087) Co-authored-by: Herb Sutter --- CppCoreGuidelines.md | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md index 9ab5e60..a4c24e2 100644 --- a/CppCoreGuidelines.md +++ b/CppCoreGuidelines.md @@ -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) @@ -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. ## C.dtor: Destructors @@ -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). ### C.32: If a class has a raw pointer (`T*`) or reference (`T&`), consider whether it might be owning @@ -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 @@ -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. ### C.46: By default, declare single-argument constructors explicit @@ -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". -### C.47: Define and initialize member variables in the order of member declaration +### C.47: Define and initialize data members in the order of member declaration ##### Reason @@ -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. ### C.49: Prefer initialization to assignment in constructors @@ -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 @@ -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: @@ -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. @@ -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() { @@ -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. }; @@ -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` instead. +* Flag `volatile T` local and data members; almost certainly you intended to use `atomic` instead. * ??? ### CP.201: ??? Signals @@ -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. ### Con.3: By default, pass pointers and references to `const`s @@ -21181,7 +21181,7 @@ Type safety profile summary: Prefer [construction](#Res-construct) or [named casts](#Res-casts-named) or `T{expression}`. * Type.5: Don't use a variable before it has been initialized: [always initialize](#Res-always). -* Type.6: Always initialize a member variable: +* 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). @@ -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. -### Discussion: Define and initialize member variables in the order of member declaration +### 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; @@ -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**: @@ -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`