Specify enumerator values only when necessary
Reason
It's the simplest. It avoids duplicate enumerator values. The default gives a consecutive set of values that is good for switch-statement implementations.
Example
enum class Col1 { red, yellow, blue };
enum class Col2 { red = 1, yellow = 2, blue = 2 }; // typo
enum class Month { jan = 1, feb, mar, apr, may, jun,
jul, august, sep, oct, nov, dec }; // starting with 1 is conventional
enum class Base_flag { dec = 1, oct = dec << 1, hex = dec << 2 }; // set of bits
Specifying values is necessary to match conventional values (e.g., Month) and where consecutive values are undesirable (e.g., to get separate bits as in Base_flag).
Enforcement
- Flag duplicate enumerator values
- Flag explicitly specified all-consecutive enumerator values
R: Resource management
This section contains rules related to resources. A resource is anything that must be acquired and (explicitly or implicitly) released, such as memory, file handles, sockets, and locks. The reason it must be released is typically that it can be in short supply, so even delayed release might do harm. The fundamental aim is to ensure that we don't leak any resources and that we don't hold a resource longer than we need to. An entity that is responsible for releasing a resource is called an owner.
There are a few cases where leaks can be acceptable or even optimal: If you are writing a program that simply produces an output based on an input and the amount of memory needed is proportional to the size of the input, the optimal strategy (for performance and ease of programming) is sometimes simply never to delete anything. If you have enough memory to handle your largest input, leak away, but be sure to give a good error message if you are wrong. Here, we ignore such cases.
- Resource management rule summary:
- R.1: Manage resources automatically using resource handles and RAII (Resource Acquisition Is Initialization)
- R.2: In interfaces, use raw pointers to denote individual objects (only)
- R.3: A raw pointer (a
T*) is non-owning - R.4: A raw reference (a
T&) is non-owning - R.5: Prefer scoped objects, don't heap-allocate unnecessarily
- R.6: Avoid non-
constglobal variables
- Allocation and deallocation rule summary:
- R.10: Avoid
malloc()andfree() - R.11: Avoid calling
newanddeleteexplicitly - R.12: Immediately give the result of an explicit resource allocation to a manager object
- R.13: Perform at most one explicit resource allocation in a single expression statement
- [R.14: Avoid
[]parameters, preferspan](/roadmap/cpp/guidelines/r-14) - R.15: Always overload matched allocation/deallocation pairs
- <a name="rr-summary-smartptrs"></a>Smart pointer rule summary:
- R.20: Use
unique_ptrorshared_ptrto represent ownership - R.21: Prefer
unique_ptrovershared_ptrunless you need to share ownership - R.22: Use
make_shared()to makeshared_ptrs - R.23: Use
make_unique()to makeunique_ptrs - R.24: Use
std::weak_ptrto break cycles ofshared_ptrs - R.30: Take smart pointers as parameters only to explicitly express lifetime semantics
- R.31: If you have non-
stdsmart pointers, follow the basic pattern fromstd - R.32: Take a
unique_ptr<widget>parameter to express that a function assumes ownership of awidget - R.33: Take a
unique_ptr<widget>¶meter to express that a function reseats thewidget - R.34: Take a
shared_ptr<widget>parameter to express shared ownership - R.35: Take a
shared_ptr<widget>¶meter to express that a function might reseat the shared pointer - R.36: Take a
const shared_ptr<widget>¶meter to express that it might retain a reference count to the object ??? - R.37: Do not pass a pointer or reference obtained from an aliased smart pointer