### Simple parameter swap example (C++) Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines An example demonstrating that parameter order is not an issue when the function's logic inherently handles the order, such as in `max(a, b)`. ```cpp int max(int a, int b); ``` -------------------------------- ### Example Usage and Error Scenario Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Provides a complete example demonstrating the usage of `user`, `user2`, and `user3` functions, highlighting the potential error when using `user2` with a base class object. ```C++ void f() { B b; user(&b); // OK user2(&b); // bad error user3(&b); // OK *if* the programmer got the some_condition check right } ``` -------------------------------- ### Complex Initialization Logic (ES.22 Bad Example 2) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example illustrates a complex initialization scenario for a variable declared early. It highlights the potential for 'use before set' bugs if not all initialization paths are correctly handled, especially with non-trivial conditions. ```cpp SomeLargeType var; // Hard-to-read CaMeLcAsEvArIaBlE if (cond) // some non-trivial condition Set(&var); else if (cond2 || !cond3) { var = Set2(3.14); } else { var = 0; for (auto& e : something) var += e; } // use var; that this isn't done too early can be enforced statically with only control flow ``` -------------------------------- ### Container initialization with {} and () Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Containers traditionally use {} for element lists and () for sizes. This example shows the distinction between vector initialization using these syntaxes. ```cpp vector v1(10); // vector of 10 elements with the default value 0 vector v2{10}; // vector of 1 element with the value 10 vector v3(1, 2); // vector of 1 element with the value 2 vector v4{1, 2}; // vector of 2 elements with the values 1 and 2 ``` -------------------------------- ### Example: Distinct Operations with Different Names Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Use distinct names for fundamentally different operations to avoid confusion. This example shows 'open_gate' and 'fopen' as unrelated operations with appropriate names. ```C++ void open_gate(Gate& g); // remove obstacle from garage exit lane void fopen(const char* name, const char* mode); // open file ``` -------------------------------- ### Buffer overflow examples with (ptr, length) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/docs/gsl-intro.md Demonstrates how passing incorrect lengths to a (ptr, length) function can lead to buffer overflows. ```cpp int a[100]; dangerous_process_ints(a, 1000); // oops: buffer overflow vector v(200); dangerous_process_ints(v.data(), 1000); // oops: buffer overflow auto remainder = find(v.begin(), v.end(), some_value); // now call dangerous_process_ints() to fill the rest of the container from *remainder to the end dangerous_process_ints(&*remainder, v.end() - remainder); // correct but convoluted ``` -------------------------------- ### C-style Variadic Function Example (error) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates a C-style variadic function 'error' that takes a severity level and a variable number of C-style strings. This example highlights the potential for crashes due to incorrect usage and lack of type safety. It requires including . ```C++ #include // "severity" followed by a zero-terminated list of char*s; write the C-style strings to cerr void error(int severity ...) { va_list ap; // a magic type for holding arguments va_start(ap, severity); // arg startup: "severity" is the first argument of error() for (;;) { // treat the next var as a char*; no checking: a cast in disguise char* p = va_arg(ap, char*); if (!p) break; cerr << p << ' '; } va_end(ap); // arg cleanup (don't forget this) cerr << '\n'; if (severity) exit(severity); } void use() { error(7, "this", "is", "an", "error", nullptr); error(7); // crash error(7, "this", "is", "an", "error"); // crash const char* is = "is"; string an = "an"; error(7, "this", is, an, "error"); // crash } ``` -------------------------------- ### ofstream Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Shows a class with a special 'not open' state that serves as its default constructed value. This class is not copyable. ```cpp // std::ofstream is not a copyable value type. // It does happen to have a default constructor // that goes along with a special "not open" state. ofstream out {"Foobar"}; // ... out << log(time, transaction); ``` -------------------------------- ### Postcondition Check with Ensures Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Use Ensures() to make postconditions explicit and enable tool use. This example checks if the first byte of a buffer is zero after memset. ```cpp void f() { char buffer[MAX]; // ... memset(buffer, 0, MAX); Ensures(buffer[0] == 0); } ``` -------------------------------- ### Self-Contained Header Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Illustrates a header file ('helpers.h') that correctly includes its own dependencies, such as the 'string' header, to ensure it works when included on its own. ```c++ #include "helpers.h" // helpers.h depends on std::string and includes ``` -------------------------------- ### Delayed Initialization Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates a scenario where delayed initialization of variables can lead to issues. It shows how to refactor using C++17 structured bindings and lambdas for better initialization. ```C++ widget i; widget j; if (cond) { // bad: i and j are initialized "late" i = f1(); j = f2(); } else { i = f3(); j = f4(); } ``` ```C++ pair make_related_widgets(bool x) { return (x) ? {f1(), f2()} : {f3(), f4()}; } auto [i, j] = make_related_widgets(cond); // C++17 ``` ```C++ auto [i, j] = [x] { return (x) ? pair{f1(), f2()} : pair{f3(), f4()} }(); // C++17 ``` ```C++ widget i = uninit; // bad widget j = uninit; // ... use(i); // possibly used before set // ... if (cond) { // bad: i and j are initialized "late" i = f1(); j = f2(); } else { i = f3(); j = f4(); } ``` -------------------------------- ### Bad Hash Specialization Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Demonstrates a thoroughly bad hash specialization that includes throwing exceptions. Avoid throwing exceptions from hash functions. ```cpp template<> struct hash { using result_type = size_t; using argument_type = My_type; size_t operator() (const My_type & x) const { size_t xs = x.s.size(); if (xs < 4) throw Bad_My_type{}; return hash()(x.s.size()) ^ trim(x.s); } }; int main() { unordered_map m; My_type mt{ "asdfg" }; m[mt] = 7; cout << m[My_type{ "asdfg" }] << '\n'; } ``` -------------------------------- ### Document preconditions with comments Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines When preconditions cannot be expressed by types, document them using comments. This example shows documenting that the argument to `sqrt` must be nonnegative. ```cpp double sqrt(double x); // x must be nonnegative ``` -------------------------------- ### Struct with Default Initialized Members Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines A struct where all members have default constructors implicitly gets a default constructor. This example shows `X` with a `string` and `vector`, both of which have default constructors, resulting in `x` being default-initialized to an empty string and an empty vector. ```cpp struct X { string s; vector v; }; X x; // means X{{}, {}}; that is the empty string and the empty vector ``` -------------------------------- ### Example: Aggregating Headers Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates a pattern where a single header file includes a set of commonly used standard library headers to provide a convenient bundle of declarations. ```c++ // basic_std_lib.h: #include #include #include #include #include ``` -------------------------------- ### C++20 sort usage example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Example of using the C++20 sort interface with a sortable type. ```cpp sort(c); ``` -------------------------------- ### Recommended Class with Default Member Initializers Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates the recommended way to initialize members using default member initializers, allowing the compiler to generate an efficient default constructor. ```C++ class X2 { string s {"default"}; int i {1}; public: // use compiler-generated default constructor // ... }; ``` -------------------------------- ### C++98 sort usage example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Example of using the C++98 sort interface with an array of doubles. ```cpp sort(data, data + 100); ``` -------------------------------- ### C++11 sort usage example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Example of calling the C++11 style sort function with a Sortable object. ```cpp sort(c); ``` -------------------------------- ### Manual resource management example (bad) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates manual resource management with potential for leaks and complexity. If an exception occurs, resources like mutexes and allocated memory can be leaked. ```cpp void send(X* x, string_view destination) { auto port = open_port(destination); my_mutex.lock(); // ... send(port, x); // ... my_mutex.unlock(); close_port(port); delete x; } ``` -------------------------------- ### Container Value Semantics Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Illustrates the concept of value semantics for a container by creating a copy and comparing it. Ensures that a container object compares equal to its copy. ```cpp void f(const Sorted_vector& v) { Sorted_vector v2 {v}; if (v != v2) cout << "insanity rules!\n"; // ... } ``` -------------------------------- ### Raw Owning Reference Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates the incorrect use of a raw reference to manage ownership of a dynamically allocated integer, highlighting the violation of non-owning principles. ```cpp void f() { int& r = *new int{7}; // bad: raw owning reference // ... delete &r; // bad: violated the rule against deleting raw pointers } ``` -------------------------------- ### Destructor Failure Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Destructors should not throw exceptions. This example shows a bad practice where a destructor might throw. ```C++ class Connection { // ... public: ~Connection() // Don't: very bad destructor { if (cannot_disconnect()) throw I_give_up{information}; // ... } }; ``` -------------------------------- ### Home-brew RTTI Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Illustrates the potential pitfalls of implementing custom RTTI using virtual functions and string comparisons. This approach can lead to implementation-defined behavior and unexpected failures. ```cpp struct B { const char* name {"B"}; // if pb1->id() == pb2->id() *pb1 is the same type as *pb2 virtual const char* id() const { return name; } // ... }; struct D : B { const char* name {"D"}; const char* id() const override { return name; } // ... }; void use() { B* pb1 = new B; B* pb2 = new D; cout << pb1->id(); // "B" cout << pb2->id(); // "D" if (pb1->id() == "D") { // looks innocent D* pd = static_cast(pb1); // ... } // ... } ``` -------------------------------- ### Template function initialization with {} and () Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates different initialization syntaxes within a template function, highlighting the distinction between direct initialization and function declaration. ```cpp template void f() { T x1(1); // T initialized with 1 T x0(); // bad: function declaration (often a mistake) T y1 {1}; // T initialized with 1 T y0 {}; // default initialized T // ... } ``` -------------------------------- ### Catching All Exceptions Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Avoid catching all exceptions in a function if no meaningful recovery action can be taken. This example shows a pattern to be avoided. ```C++ void f() // bad { try { // ... } catch (...) { // no action throw; // propagate exception } } ``` -------------------------------- ### Pointer-based Initialization on First Use (with potential leak) Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines This example demonstrates a less safe way to achieve initialization on first use using a raw pointer. It highlights the potential for memory leaks if not managed carefully, especially in multi-threaded environments where destruction needs synchronization. ```cpp X& myX() { static auto p = new X {3}; return *p; // potential leak } ``` -------------------------------- ### STL-style Container Definition Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md An incomplete but illustrative example of defining a custom container, 'Sorted_vector', adhering to STL conventions for constructors, assignments, and member storage. ```cpp template class Sorted_vector { using value_type = T; // ... iterator types ... Sorted_vector() = default; Sorted_vector(initializer_list); // initializer-list constructor: sort and store Sorted_vector(const Sorted_vector&) = default; Sorted_vector(Sorted_vector&&) noexcept = default; Sorted_vector& operator=(const Sorted_vector&) = default; // copy assignment Sorted_vector& operator=(Sorted_vector&&) noexcept = default; // move assignment ~Sorted_vector() = default; Sorted_vector(const std::vector& v); // store and sort Sorted_vector(std::vector&& v); // sort and "steal representation" const T& operator[](int i) const { return rep[i]; } // no non-const direct access to preserve order void push_back(const T&); // insert in the right place (not necessarily at back) void push_back(T&&); // insert in the right place (not necessarily at back) // ... cbegin(), cend() ... private: std::vector rep; // use a std::vector to hold elements }; template bool operator==(const Sorted_vector&, const Sorted_vector&); template bool operator!=(const Sorted_vector&, const Sorted_vector&); // ... ``` -------------------------------- ### Template Initialization in C++ Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Demonstrates initialization within a template function, contrasting direct initialization with parentheses and braces, and highlighting the common mistake of declaring a function with (). ```cpp template void f() { T x1(1); // T initialized with 1 T x0(); // bad: function declaration (often a mistake) T y1 {1}; // T initialized with 1 T y0 {}; // default initialized T // ... } ``` -------------------------------- ### C++98 sort usage example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Example of using the C++98 generic sort function with iterators to sort an array of doubles. This is more idiomatic C++ than using qsort. ```cpp sort(data, data + 100); ``` -------------------------------- ### Basic Integer Input and Output Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines A simple function demonstrating reading an integer from an input stream and printing it to an output stream, including basic error checking. ```cpp void read_and_print() // bad { int x; cin >> x; // check for errors cout << x << "\n"; } ``` -------------------------------- ### Avoid naked new and delete Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Direct resource management using 'new' and 'delete' is error-prone. Prefer RAII (Resource Acquisition Is Initialization) or smart pointers instead. ```cpp void f(int n) { auto p = new X[n]; // n default constructed Xs // ... delete[] p; } ``` -------------------------------- ### Bad Example: Overloading '+' for Subtraction Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Avoid overloading operators in a way that violates their conventional meaning. This example incorrectly overloads the '+' operator to perform subtraction. ```C++ X operator+(X a, X b) { return a.v - b.v; } // bad: makes + subtract ``` -------------------------------- ### Pair Struct Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md A basic 'struct' template for a pair of elements. This example illustrates a common use case for 'struct' where all members are intended to be public and independently modifiable. ```cpp template struct pair { T a; U b; // ... }; ``` -------------------------------- ### Container Initialization Syntax Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines For containers, `{...}` is traditionally used for lists of elements, while `(...)` is used for sizes. Be mindful of this convention to avoid confusion. ```cpp vector v1(10); // vector of 10 elements with the default value 0 vector v2{10}; // vector of 1 element with the value 10 vector v3(1, 2); // vector of 1 element with the value 2 vector v4{1, 2}; // vector of 2 element with the values 1 and 2 ``` -------------------------------- ### Class with Default Constructor and Default Member Initializers Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines This example demonstrates how to correctly implement a default constructor for a `Date` class using `= default` and provides default member initializers for day, month, and year. This allows for seamless integration with containers like `std::vector`. ```cpp class Date { public: Date(int dd, int mm, int yyyy); Date() = default; // [See also](#Rc-default) // ... private: int dd = 1; int mm = 1; int yyyy = 1970; // ... }; vector vd1(1000); ``` -------------------------------- ### Holding Lock Too Long (Bad Example) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example shows a function where a mutex is held for longer than necessary, encompassing preparation and cleanup code that doesn't require the lock. This can increase contention. ```C++ void do_something() // bad { unique_lock lck(my_lock); do0(); // preparation: does not need lock do1(); // transaction: needs locking do2(); // cleanup: does not need locking } ``` -------------------------------- ### Class Definition Initialization (Good) Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Shows the preferred method for defining and initializing a struct. ```cpp struct Data { /*...*/ }; Data data{ /*...*/ }; ``` -------------------------------- ### Avoid Two-Phase Initialization in C++ Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates the problems with splitting object initialization into a constructor and a separate Init() method. This approach can lead to objects in an invalid state and is error-prone. ```cpp // Old conventional style: many problems class Picture { int mx; int my; int * data; public: // main problem: constructor does not fully construct Picture(int x, int y) { mx = x; // also bad: assignment in constructor body // rather than in member initializer my = y; data = nullptr; // also bad: constant initialization in constructor // rather than in member initializer } ~Picture() { Cleanup(); } // ... // bad: two-phase initialization bool Init() { // invariant checks if (mx <= 0 || my <= 0) { return false; } if (data) { return false; } data = (int*) malloc(mx*my*sizeof(int)); // also bad: owning raw * and malloc return data != nullptr; } // also bad: no reason to make cleanup a separate function void Cleanup() { if (data) free(data); data = nullptr; } }; Picture picture(100, 0); // not ready-to-use picture here // this will fail.. if (!picture.Init()) { puts("Error, invalid picture"); } // now have an invalid picture object instance. ``` -------------------------------- ### Unsigned Integer Conversion Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Demonstrates how negative values are converted to large unsigned integers and how unsigned arithmetic can lead to unexpected results due to wraparound. Use signed integers for values that can be negative. ```cpp unsigned int u1 = -2; // Valid: the value of u1 is 4294967294 int i1 = -2; unsigned int u2 = i1; // Valid: the value of u2 is 4294967294 int i2 = u2; // Valid: the value of i2 is -2 ``` ```cpp unsigned area(unsigned height, unsigned width) { return height*width; } // [see also](#Ri-expects) // ... int height; cin >> height; auto a = area(height, 2); // if the input is -2 a becomes 4294967292 ``` -------------------------------- ### Bad Example: Repetitive Constructor Logic Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This code shows a 'bad' example of constructor implementation where common initialization logic is repeated, increasing the chance of errors and making maintenance harder. ```cpp class Date { // BAD: repetitive int d; Month m; int y; public: Date(int dd, Month mm, year yy) :d{dd}, m{mm}, y{yy} { if (!valid(d, m, y)) throw Bad_date{}; } Date(int dd, Month mm) :d{dd}, m{mm} y{current_year()} { if (!valid(d, m, y)) throw Bad_date{}; } // ... }; ``` -------------------------------- ### C qsort usage example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines An example of using the C qsort function to sort an array of doubles. This demonstrates the need to manually specify the size of each element and provide a comparison function. ```c double data[100]; // ... fill a ... // 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); ``` -------------------------------- ### Abstract class as interface (better example) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Shows a better approach using a pure abstract class with only pure virtual functions, defining a clear interface without imposing state on derived classes. ```cpp class Shape { // better: Shape is a pure interface public: virtual Point center() const = 0; // pure virtual functions virtual void draw() const = 0; virtual void rotate(int) = 0; // ... // ... no data members ... // ... virtual ~Shape() = default; }; ``` -------------------------------- ### Input Operations and Initialization Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Discusses initialization for variables that are targets of input operations. It shows that simple variables should not be considered exceptions and suggests initializing them to an acceptable default value. ```C++ int i; // bad // ... cin >> i; ``` ```C++ int i2 = 0; // better, assuming that zero is an acceptable value for i2 // ... cin >> i2; ``` -------------------------------- ### Bad Example: Uninitialized Member with Inheriting Constructors Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This 'bad' example illustrates a potential issue when using inheriting constructors: if the derived class has new members, they might remain uninitialized if not explicitly handled. ```cpp struct Rec2 : public Rec { int x; using Rec::Rec; }; Rec2 r {"foo", 7}; int val = r.x; // uninitialized ``` -------------------------------- ### GSL span_p for Predicate-Terminated Sequences Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Use span_p to represent a sequence view defined by a starting pointer and a predicate. The sequence extends from the start pointer up to, but not including, the first element for which the predicate returns true. ```cpp span_p // {p, predicate} [p:q) where q is the first element for which predicate(*p) is true ``` -------------------------------- ### Avoid goto for Cleanup in C++ Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Shows an example of using 'goto exit' for cleanup, which is error-prone and considered an outdated practice. This pattern should be replaced with modern C++ exception handling and RAII. ```cpp void do_something(int n) { if (n < 100) goto exit; // ... int* p = (int*) malloc(n); // ... if (some_error) goto exit; // ... exit: free(p); } and spot the bug. ``` -------------------------------- ### Unconditional wait() (Bad Example) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates a potential issue where `cv.wait(lock)` is called without a condition. This can lead to missed wakeups or unnecessary blocking if another thread consumes the notification before this thread processes it. ```C++ std::condition_variable cv; std::mutex mx; void thread1() { while (true) { // do some work ... std::unique_lock lock(mx); cv.notify_one(); // wake other thread } } void thread2() { while (true) { std::unique_lock lock(mx); cv.wait(lock); // might block forever // do work ... } } ``` -------------------------------- ### Example: Overloading Functions for Similar Operations Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Use function overloading for operations that are logically equivalent across different types to avoid verbosity and support generic programming. This example shows overloaded 'print' functions. ```C++ void print(int a); void print(int a, int base); void print(const string&); ``` -------------------------------- ### Potentially Throwing Move Operations (C.66 Bad Example) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md An example of move operations that are not `noexcept` and can throw exceptions. This is considered bad practice because it relies on copy operations which may involve allocation and thus can fail. ```C++ template class Vector2 { public: Vector2(Vector2&& a) noexcept { *this = a; } // just use the copy Vector2& operator=(Vector2&& a) noexcept { *this = a; } // just use the copy // ... private: T* elem; int sz; }; ``` -------------------------------- ### Class Member Initialization Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Illustrates initialization of class members, including default initialization, member initializer lists, and const members. Highlights potential issues with uninitialized members. ```C++ class X { public: X(int i, int ci) : m2{i}, cm2{ci} {} // ... private: int m1 = 7; int m2; int m3; const int cm1 = 7; const int cm2; const int cm3; }; ``` -------------------------------- ### Pair Struct Example Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines A basic template struct 'pair' with public members 'a' and 'b'. This example highlights that without access control, members can be arbitrarily changed by users, making it difficult to enforce relationships or invariants. ```cpp template struct pair { T a; U b; // ... }; ``` -------------------------------- ### Demonstrate {} Initialization in C++ Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Illustrates various uses of {} initialization for vectors, member initializers, variables, and struct members. Use plain {}-initialization unless you specifically want to disable explicit constructors. ```cpp auto p = new vector {1, 2, 3, 4, 5}; // initialized vector ``` ```cpp D::D(int a, int b) :m{a, b} { // member initializer (e.g., m might be a pair) // ... }; ``` ```cpp X var {}; // initialize var to be empty ``` ```cpp struct S { int m {7}; // default initializer for a member // ... }; ``` -------------------------------- ### Postcondition Check for Buffer Initialization Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Demonstrates a postcondition check for buffer initialization. The Ensures() call verifies that the first element is zero after memset. ```cpp void f() // better { char buffer[MAX]; // ... memset(buffer, 0, sizeof(buffer)); Ensures(buffer[0] == 0); } ``` -------------------------------- ### Safe file handling with RAII in C++ Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Illustrates the safe and efficient way to handle file resources using RAII (Resource Acquisition Is Initialization) with `std::ifstream`. This avoids manual resource management and potential leaks. ```cpp void f(const string& name) { ifstream f{name}; // open the file vector buf(1024); // ... } ``` -------------------------------- ### Bad Example: Using Different Names for Equivalent Operations Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Avoid using different function names for logically equivalent operations, as it leads to verbosity and hinders generic programming. This example contrasts overloaded 'print' with distinct function names. ```C++ void print_int(int a); void print_based(int a, int base); void print_string(const string&); ``` -------------------------------- ### Prefer Initialization to Assignment in Constructors Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Use member initialization lists to directly construct members, which is more efficient and prevents 'use before set' errors. The 'good' example initializes `s1` directly, while the 'bad' example uses assignment after default construction. ```cpp class A { // Good string s1; public: A(czstring p) : s1{p} { } // GOOD: directly construct (and the C-string is explicitly named) // ... }; ``` ```cpp class B { // BAD string s1; public: B(const char* p) { s1 = p; } // BAD: default constructor followed by assignment // ... }; ``` ```cpp class C { // UGLY, aka very bad int* p; public: C() { cout << *p; p = new int{10}; } // accidental use before initialized // ... }; ``` ```cpp class D { // Good string s1; public: A(string_view v) : s1{v} { } // GOOD: directly construct // ... }; ``` -------------------------------- ### Initialization on First Use with Static Local in C++ Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This pattern provides initialization on first use and handles initialization order issues effectively, especially in multi-threaded environments. ```cpp X& myX() { static X my_x {3}; return my_x; } ``` -------------------------------- ### Lock-free linked list insertion (bad example) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates a flawed attempt at lock-free insertion into a linked list. It is prone to the ABA problem and difficult to debug. Avoid implementing custom lock-free data structures without expert knowledge. ```cpp extern atomic head; // the shared head of a linked list Link* nh = new Link(data, nullptr); // make a link ready for insertion Link* h = head.load(); // read the shared head of the list do { if (h->data <= data) break; // if so, insert elsewhere nh->next = h; // next element is the previous head } while (!head.compare_exchange_weak(h, nh)); // write nh to head or to h ``` -------------------------------- ### Direct vs. Copy Initialization with {} and = Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Highlights the difference between direct initialization ({}) and copy initialization (=) with explicit constructors. {} accepts explicit constructors, while = does not. ```cpp struct Z { explicit Z() {} }; ``` ```cpp Z z1{}; // OK: direct initialization, so we use explicit constructor ``` ```cpp Z z2 = {}; // error: copy initialization, so we cannot use the explicit constructor ``` -------------------------------- ### Avoid Over-parameterizing Members in Templates (SCARY) Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Illustrates a 'bad' example where a nested `Link` struct depends on the template parameter `A` (allocator) even though it doesn't use it, leading to redundant instantiations. The 'good' example refactors `Link` into a non-templated struct, reducing dependencies. ```C++ template> // requires Regular && Allocator class List { public: struct Link { // does not depend on A T elem; Link* pre; Link* suc; }; using iterator = Link*; iterator first() const { return head; } // ... private: Link* head; }; List lst1; List lst2; ``` ```C++ template struct Link { T elem; Link* pre; Link* suc; }; template> // requires Regular && Allocator class List2 { public: using iterator = Link*; iterator first() const { return head; } // ... private: Link* head; }; List2 lst1; List2 lst2; ``` -------------------------------- ### Constructor Initialization Order Example Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates incorrect initialization order in a constructor, leading to potential bugs when members are used before construction. Ensure data members are initialized in the order they are declared. ```cpp class Employee { string email, first, last; public: Employee(const char* firstName, const char* lastName); // ... }; Employee::Employee(const char* firstName, const char* lastName) : first(firstName), last(lastName), // BAD: first and last not yet constructed email(first + "." + last + "@acme.com") {} ``` -------------------------------- ### Resource cleanup using goto for error exits Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Illustrates resource cleanup using `goto` statements to centralize cleanup logic at the end of the function. This technique can improve readability for complex error paths but requires careful management of scopes. ```cpp std::pair user() { error_indicator err = 0; int res = 0; Gadget g1 = make_gadget(17); if (!g1.valid()) { err = g1_error; goto g1_exit; } { Gadget g2 = make_gadget(31); if (!g2.valid()) { err = g2_error; goto g2_exit; } if (all_foobar(g1, g2)) { err = foobar_error; goto g2_exit; } // ... g2_exit: if (g2.valid()) cleanup(g2); } g1_exit: if (g1.valid()) cleanup(g1); return {res, err}; } ``` -------------------------------- ### Prefer In-Class Initializers for Constant Initializers Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Use in-class initializers for constant values to make initialization explicit across all constructors and avoid repetition. The 'bad' example demonstrates uninitialized members and inconsistent initialization values, while the 'good' example (X2) shows proper in-class initialization. ```cpp class X { int i; string s; int j; public: X() :i{666}, s{"qqq"} { } // j is uninitialized X(int ii) :i{ii} {} // s is "" and j is uninitialized // ... }; ``` ```cpp class X2 { int i {666}; string s {"qqq"}; int j {0}; public: X2() = default; // all members are initialized to their defaults X2(int ii) :i{ii} {} // s and j initialized to their defaults // ... }; ``` ```cpp class X3 { // BAD: inexplicit, argument passing overhead int i; string s; int j; public: X3(int ii = 666, const string& ss = "qqq", int jj = 0) :i{ii}, s{ss}, j{jj} { } // all members are initialized to their defaults // ... }; ``` -------------------------------- ### Explicit Month Return Type and Const Correctness in C++ Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Prefer explicit return types and const correctness for member functions to improve clarity and prevent bugs. The 'do' example shows a const member function returning a specific type, while the 'don't' example is ambiguous. ```cpp class Date { // ... public: Month month() const; // do int month(); // don't // ... }; ``` -------------------------------- ### Bad example of struct and function with wasted resources Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates a struct with inefficient member layout and a function that uses manual memory management and redundant string copying, leading to wasted time and space. The custom copy operations also disable move semantics, slowing down return operations. ```C++ struct X { char ch; int i; string s; char ch2; X& operator=(const X& a); X(const X&); }; X waste(const char* p) { if (!p) throw Nullptr_error{}; int n = strlen(p); auto buf = new char[n]; if (!buf) throw Allocation_error{}; for (int i = 0; i < n; ++i) buf[i] = p[i]; // ... manipulate buffer ... X x; x.ch = 'a'; x.s = string(n); // give x.s space for *p for (gsl::index i = 0; i < x.s.size(); ++i) x.s[i] = buf[i]; // copy buf into x.s delete[] buf; return x; } void driver() { X x = waste("Typical argument"); // ... } ``` -------------------------------- ### dyn_array Operations: Get Size Source: https://github.com/isocpp/cppcoreguidelines/blob/master/docs/dyn_array.md Return the number of elements in the dyn_array. This operation is noexcept. ```cpp constexpr size_t size() const noexcept; ``` -------------------------------- ### Use C++17 string_view for Initialization Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Employ `std::string_view` (or `gsl::span`) as a more general way to present string arguments for direct construction, improving efficiency. ```cpp class D { // Good string s1; public: D(string_view v) : s1{v} { } // GOOD: directly construct // ... }; ``` -------------------------------- ### Compile-time vs. Run-time Initialization Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Compares old-style dynamic initialization with a function call at runtime to modern compile-time initialization using `constexpr`. Compile-time initialization reduces runtime overhead and avoids potential data races on constants. ```cpp double square(double d) { return d*d; } static double s2 = square(2); // old-style: dynamic initialization ``` ```cpp constexpr double ntimes(double d, int n) // assume 0 <= n { double m = 1; while (n--) m *= d; return m; } constexpr double s3 {ntimes(2, 3)}; // modern-style: compile-time initialization ``` -------------------------------- ### dyn_array Operations: Get Data Pointer Source: https://github.com/isocpp/cppcoreguidelines/blob/master/docs/dyn_array.md Return a pointer to the underlying array. This operation is noexcept. ```cpp constexpr T* data() noexcept; constexpr const T* data() const noexcept; ``` -------------------------------- ### Misreadable Variable Names Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Example of variable names that are easily misread due to similar characters or spelling. ```cpp int oO01lL = 6; // bad int splunk = 7; int splonk = 8; // bad: splunk and splonk are easily confused ``` -------------------------------- ### Input Parameters: Pass by Value or Const Reference Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates standard ways to pass input parameters. 'int' is passed by value for simplicity and efficiency. 'string' is passed by const reference as it's not as cheap to copy. ```C++ int multiply(int, int); // just input ints, pass by value // suffix is input-only but not as cheap as an int, pass by const& string& concatenate(string&, const string& suffix); ``` -------------------------------- ### Wrapping Const-Incorrect Functions Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates how to wrap const-incorrect functions with a const-correct wrapper to encapsulate the const_cast. ```C++ /* You might need to cast away `const` when calling `const`-incorrect functions. Prefer to wrap such functions in inline `const`-correct wrappers to encapsulate the cast in one place. */ ``` -------------------------------- ### Thread Creation with Joining Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Shows how to create `std::thread` objects and ensure they complete execution by calling `join()`. This prevents potential bugs related to unjoined threads. ```cpp void f() { std::cout << "Hello "; } struct F { void operator()() { std::cout << "parallel world "; } }; int main() { std::thread t1{f}; // f() executes in separate thread std::thread t2{F()}; // F()() executes in separate thread t1.join(); t2.join(); } ``` -------------------------------- ### Avoid Unnamed Enumerations Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Shows an example of an unnamed enumeration, which is discouraged because the values are not clearly related and can be replaced by `constexpr` values. ```c++ enum { red = 0xFF0000, scale = 4, is_signed = 1 }; ``` -------------------------------- ### Custom Container Initialization with Count Struct Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md Demonstrates a solution to container initialization ambiguity using a custom Count struct. ```cpp struct Count { int n; }; template class Vector { public: Vector(Count n); // n default-initialized elements Vector(initializer_list init); // init.size() elements // ... }; Vector v1{10}; Vector v2{Count{10}}; Vector v3{Count{10}}; // yes, there is still a very minor problem ``` -------------------------------- ### Demonstrate Unsigned Arithmetic Behavior Source: https://github.com/isocpp/cppcoreguidelines/wiki/CppCoreGuidelines Illustrates the surprising results of unsigned arithmetic, especially in mixed signed and unsigned operations. Use unsigned types only when modulo arithmetic is explicitly desired and document this reliance. ```cpp template T subtract(T x, T2 y) { return x - y; } void test() { int s = 5; unsigned int us = 5; cout << subtract(s, 7) << '\n'; // -2 cout << subtract(us, 7u) << '\n'; // 4294967294 cout << subtract(s, 7u) << '\n'; // -2 cout << subtract(us, 7) << '\n'; // 4294967294 cout << subtract(s, us + 2) << '\n'; // -2 cout << subtract(us, s + 2) << '\n'; // 4294967294 } ``` -------------------------------- ### Good: Returning Vector by Value for Ownership Transfer Source: https://github.com/isocpp/cppcoreguidelines/blob/master/CppCoreGuidelines.md This example demonstrates a safe way to transfer ownership of dynamically allocated data. Returning a `vector` by value (`f5`) allows for efficient move semantics and ensures that the ownership and all necessary information (like size) are transferred correctly. ```C++ vector f5(int n) // OK: move { vector v(n); // ... initialize v ... return v; } ```