### C++: File naming conventions (.h and .cpp) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ snippet shows the recommended file naming convention, using `.h` for interface files (declarations) and `.cpp` for implementation files (definitions). It includes an example of a correct `foo.h` and `foo.cpp`, and a 'bad' example where a definition in `foo.h` leads to linker errors. ```cpp // foo.h: extern int a; // a declaration extern void foo(); // foo.cpp: int a; // a definition void foo() { ++a; } ``` ```cpp // foo.h: int a; // a definition void foo() { ++a; } ``` -------------------------------- ### C++ Class Initialization: Bad vs. Good Constructor Practices Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Compares a poorly implemented C++ constructor with member-wise assignment and raw pointer management to a well-designed constructor using member initializer lists and standard library containers (vector). Highlights issues like two-phase initialization and raw resource management in the bad example, and proper initialization and RAII in the good example. ```C++ // 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. ``` ```C++ class Picture { int mx; int my; vector data; static int check_size(int size) { // invariant check Expects(size > 0); return size; } public: // even better would be a class for a 2D Size as one single parameter Picture(int x, int y) : mx(check_size(x)) , my(check_size(y)) // now we know x and y have a valid size , data(mx * my) // will throw std::bad_alloc on error { // picture is ready-to-use } // compiler generated dtor does the job. (also see C.21) // ... }; Picture picture1(100, 100); // picture1 is ready-to-use here... // not a valid size for y, // default contract violation behavior will call std::terminate then Picture picture2(100, 0); // not reach here... ``` -------------------------------- ### Avoid Overloading for Logically Different Operations (C++ Example) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates how overloading should be used for logically equivalent operations, not fundamentally different ones. The example contrasts good practice (different names for 'open_gate' and 'fopen') with bad practice (overloading 'open' for distinct actions), highlighting potential confusion and type system benefits. ```cpp // Good practice: // void open_gate(Gate& g); // void fopen(const char* name, const char* mode); // Bad practice: // void open(Gate& g); // void open(const char* name, const char* mode = "r"); ``` -------------------------------- ### C++ Core Guidelines: Range Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the concept of a 'range' in C++ using a common mathematical notation for a sequence of values. ```text range : a sequence of values that can be described by a start point and an end point. For example, `[0:5)` means the values 0, 1, 2, 3, and 4. ``` -------------------------------- ### C++ Initializer List for Sequences Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates how to use an initializer list with `auto` to create a sequence of values, specifically an `initializer_list` in this example. ```cpp auto fib10 = {1, 1, 2, 3, 5, 8, 13, 21, 34, 55}; // fib10 is a list ``` -------------------------------- ### Implicit Default Constructor with Default Member Initializers (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates how a class with members that all have default constructors implicitly gets a default constructor. This example shows 'X' with string and vector members. ```cpp struct X { string s; vector v; }; X x; // means X{ { }, { } }; that is the empty string and the empty vector ``` -------------------------------- ### Illustrate Overloading for Logically Equivalent Operations (C++ Example) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Provides examples of function overloading for conceptually similar operations. 'print' functions taking different types are shown as good practice, whereas renaming similar operations like 'print_int' and 'print_string' is discouraged due to verbosity and inhibition of generic programming. ```cpp void print(int a); void print(int a, int base); void print(const string&); // Discouraged alternative: // void print_int(int a); // void print_based(int a, int base); // void print_string(const string&); ``` -------------------------------- ### C++ Pure Function Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A simple example of a pure function in C++. A pure function always produces the same output for the same input and has no side effects. This makes them easier to reason about, optimize, and parallelize. ```cpp template auto square(T t) { return t * t; } ``` -------------------------------- ### Use gsl::index for Subscripts (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index These code examples illustrate the recommended use of `gsl::index` for safer and more expressive array and vector indexing in C++. The 'bad' examples highlight potential issues with using `int`, `unsigned`, `auto`, and `size_type` for indexing, while the 'good' examples demonstrate how `gsl::index` provides a safer and more consistent approach. ```C++ vector vec = /*...*/; for (int i = 0; i < vec.size(); i += 2) // might not be big enough cout << vec[i] << '\n'; for (unsigned i = 0; i < vec.size(); i += 2) // risk wraparound cout << vec[i] << '\n'; for (auto i = 0; i < vec.size(); i += 2) // might not be big enough cout << vec[i] << '\n'; for (vector::size_type i = 0; i < vec.size(); i += 2) // verbose cout << vec[i] << '\n'; for (auto i = vec.size()-1; i >= 0; i -= 2) // bug cout << vec[i] << '\n'; for (int i = vec.size()-1; i >= 0; i -= 2) // might not be big enough cout << vec[i] << '\n'; ``` ```C++ vector vec = /*...*/; for (gsl::index i = 0; i < vec.size(); i += 2) // ok cout << vec[i] << '\n'; for (gsl::index i = vec.size()-1; i >= 0; i -= 2) // ok cout << vec[i] << '\n'; ``` -------------------------------- ### Condition Variable Wait with Predicate Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Provides an example of a synchronized queue using `std::condition_variable` and `std::mutex`. The `get` method uses a predicate with `cv.wait` to prevent spurious wakeups and ensure data is available before proceeding. ```C++ template class Sync_queue { public: void put(const T& val); void put(T&& val); void get(T& val); private: mutex mtx; condition_variable cond; // this controls access list q; }; template void Sync_queue::put(const T& val) { lock_guard lck(mtx); q.push_back(val); cond.notify_one(); } template void Sync_queue::get(T& val) { unique_lock lck(mtx); cond.wait(lck, [this] { return !q.empty(); }); // prevent spurious wakeup val = q.front(); q.pop_front(); } ``` -------------------------------- ### Handle Division by Zero (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index These code examples illustrate how to handle division by zero errors in C++. The 'bad' example shows a function without proper checks, while the 'good' examples demonstrate the use of preconditions to ensure the divisor is not zero, and the use of floating point numbers to avoid the problem altogether. ```C++ int divide(int a, int b) { // BAD, should be checked (e.g., in a precondition) return a / b; } ``` ```C++ int divide(int a, int b) { // good, address via precondition (and replace with contracts once C++ gets them) Expects(b != 0); return a / b; } double divide(double a, double b) { // good, address via using double instead return a / b; } ``` -------------------------------- ### C++ Macro and Enum Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the use of a macro for comparison and an enum for direction constants. It highlights a switch statement using these constants. ```cpp // somewhere in some header: #define NE != // somewhere else in some other header: enum Coord { N, NE, NW, S, SE, SW, E, W }; // somewhere third in some poor programmer's .cpp: switch (direction) { case N: // ... case NE: // ... // ... } ``` -------------------------------- ### C-style Container with void* (Bad Example) (C) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Presents a C-style `Container` implementation using `void*` to store elements of an unspecified type. This approach is error-prone, bypasses type safety, and hinders compiler optimizations, serving as a negative example compared to template-based containers. ```c class Container { // ... void* elem; // points to size elements of some type int sz; }; Container c(10, sizeof(double)); ((double*) c.elem)[7] = 9.9; ``` -------------------------------- ### Constructors for Convenience Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Provides an example of C++ constructors used for convenience, even when a class doesn't strictly enforce an invariant. These constructors allow for flexible object initialization using different argument types. ```cpp struct Rec { string s; int i {0}; Rec(const string& ss) : s{ss} {} Rec(int ii) :i{ii} {} }; Rec r1 {7}; Rec r2 {"Foo bar"}; ``` -------------------------------- ### C++ Structured Binding Example (C++17) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Shows how structured bindings in C++17 can be used to introduce multiple variables from a single declaration, which is an allowed exception to the single-declaration-per-line rule. ```cpp auto [ iter, inserted ] = m.insert_or_assign(k, val); if (inserted) { /* new entry was inserted */ } ``` -------------------------------- ### C++: Avoid multiple statements on one line Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ example illustrates the rule against placing multiple statements on a single line to improve readability. It shows 'don't' examples where statements are crammed together. ```cpp int x = 7; char* p = 29; // don't int x = 7; f(x); ++x; // don't ``` -------------------------------- ### Move Constructor Implementation (C++ Example) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the implementation of a move constructor for a class `X`. This constructor efficiently transfers resources from a source object (`a`) to the newly created object, leaving the source in a valid (empty) state. ```cpp class X { // OK: value semantics public: X(); X(X&& a) noexcept; // move X X& operator=(X&& a) noexcept; // move-assign X void modify(); // change the value of X // ... ~X() { delete[] p; } private: T* p; int sz; }; X::X(X&& a) noexcept :p{a.p}, sz{a.sz} // steal representation { a.p = nullptr; // set to "empty" a.sz = 0; } void use() { X x{}; // ... X y = std::move(x); x = X{}; // OK } // OK: x can be destroyed ``` -------------------------------- ### C++ Core Guidelines - Philosophical Rules Summary Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A summary of the core philosophical rules guiding C++ development, emphasizing directness, safety, and efficiency. ```text P.1: Express ideas directly in code P.2: Write in ISO Standard C++ P.3: Express intent P.4: Ideally, a program should be statically type safe P.5: Prefer compile-time checking to run-time checking P.6: What cannot be checked at compile time should be checkable at run time P.7: Catch run-time errors early P.8: Don’t leak any resources P.9: Don’t waste time or space P.10: Prefer immutable data to mutable data P.11: Encapsulate messy constructs, rather than spreading through the code P.12: Use supporting tools as appropriate P.13: Use support libraries as appropriate ``` -------------------------------- ### STL-style Sorted_vector container Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Provides an example of a `Sorted_vector` class designed following STL conventions, including constructors, assignment operators, and basic access methods. ```cpp // simplified (e.g., no allocators): 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&); // ... ``` -------------------------------- ### Returning Values vs. Output Parameters (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the preference for returning values directly over using output parameters for clarity and safety. It shows a correct example of returning pointers to elements and an incorrect example of using an output parameter for the same purpose. This guideline applies to simple return types and emphasizes avoiding misuse of reference parameters. ```cpp // OK: return pointers to elements with the value x vector find_all(const vector&, int x); // Bad: place pointers to elements with value x in-out void find_all(const vector&, vector& out, int x); ``` -------------------------------- ### C++ for_each algorithm for element processing Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates using the `for_each` algorithm from the Ranges TS in C++ to express the intent of processing elements in a container. It includes examples for sequential and parallel execution. ```cpp for_each(v, [](int x) { /* do something with the value of x */ }); for_each(par, v, [](int x) { /* do something with the value of x */ }); ``` -------------------------------- ### Self-Contained Header File Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Shows a scenario where a header file ('helpers.h') depends on `std::string` and correctly includes the `` header itself. This ensures that clients including 'helpers.h' do not need to manage its dependencies. ```cpp #include "helpers.h" // helpers.h depends on std::string and includes ``` -------------------------------- ### Prefer C++ over C Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Highlights the differences between C and C++ regarding type safety and implicit casting, showing an example of unsafe C-style casting. ```C++ char ch = 7; void* pv = &ch; int* pi = pv; // not C++ *pi = 999; // overwrite sizeof(int) bytes near &ch ``` -------------------------------- ### Thread-Safe Initialization with std::call_once Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates how to perform initialization code that should execute only once across multiple threads using std::call_once. This is a standard C++ pattern for ensuring thread-safe singleton-like behavior or one-time setup. ```cpp void f() { static std::once_flag my_once_flag; std::call_once(my_once_flag, []() { // do this only once }); // ... } ``` -------------------------------- ### Class X with Inconsistent Initializers - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A 'BAD' example of class 'X' showing inconsistent initialization of members across different constructors. Some members are uninitialized, and default values vary. ```cpp class X { // BAD 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 // ... }; ``` -------------------------------- ### Good Header Inclusion Order Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the recommended practice of including all necessary header files at the beginning of a source file to ensure that declarations are available before they are used, minimizing context dependencies. ```cpp #include #include #include // ... my code here ... ``` -------------------------------- ### Move Pointer Implementation Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the implementation of moving a pointer from one object to another, often seen in move assignment operators. It handles self-move scenarios where the source and destination are the same. ```cpp // move from other.ptr to this->ptr T* temp = other.ptr; other.ptr = nullptr; delete ptr; // in self-move, this->ptr is also null; delete is a no-op ptr = temp; // in self-move, the original ptr is restored ``` -------------------------------- ### RAII for Gadget Construction in C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates a problematic way of handling potential exceptions during object construction and subsequent cleanup using naked pointers. It shows a better RAII-based alternative. ```cpp void f(zstring s) { Gadget* p; try { p = new Gadget(s); // ... delete p; } catch (Gadget_construction_failure) { delete p; throw; } } void f2(zstring s) { Gadget g {s}; } ``` -------------------------------- ### Consistent Indentation Style in C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This example demonstrates the importance of consistent indentation in C++ for readability and preventing bugs. It shows both a potentially problematic style and a recommended approach for single statements following control structures. ```c++ int i; for (i = 0; i < max; ++i); // bug waiting to happen if (i == j) return i; // Recommended style for single statements: if (i < 0) error("negative argument"); ``` -------------------------------- ### C++ Resource Management: Bad goto vs. RAII and Exceptions Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates a C++ code snippet using `goto` for error handling and resource cleanup, highlighting its error-prone nature. The alternative suggests using exceptions and RAII (Resource Acquisition Is Initialization) for safer and more robust resource management. ```C++ void do_something(int n) { if (n < 100) goto exit; // ... int* p = (int*) malloc(n); // ... if (some_error) goto_exit; // Assuming 'goto_exit' is a typo and should be 'goto exit' // ... exit: free(p); } ``` -------------------------------- ### Class Foo with Misleading Initializer Order - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A 'BAD' example of a class 'Foo' where member initializers in the constructor are in a different order than their declaration, leading to confusion and errors. ```cpp class Foo { int m1; int m2; public: Foo(int x) :m2{x}, m1{++x} { } // BAD: misleading initializer order // ... }; Foo x(1); // surprise: x.m1 == x.m2 == 2 ``` -------------------------------- ### C++ Name Shadowing Example (Bad) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates a C++ code example where a variable 'd' is redeclared in an inner scope, leading to potential confusion and bugs. ```cpp int d = 0; // ... if (cond) { // ... d = 9; // ... } else { // ... int d = 7; // ... d = value_to_be_returned; // ... } return d; ``` -------------------------------- ### Parameter Passing Strategies Overview Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates different parameter passing strategies based on their intended use: simple input, input-only with potential cost, and input-only with ownership transfer. ```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); void sink(unique_ptr); // input only, and moves ownership of the widget ``` -------------------------------- ### Creating a Vector of Sorted Sequences with Default Constructor Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the use of a default constructor for a container of `Sorted_sequence` objects. This example shows how to create a vector with a specified number of `Sorted_sequence` elements, each initialized to an empty state. ```cpp vector> vs(100); // 100 Sorted_sequences each with the value "" ``` -------------------------------- ### Class String with Implicit Conversion Constructor - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A 'BAD' example of a 'String' class with a single-argument constructor that is not explicit, leading to unintended conversions. An example of implicit conversion is shown. ```cpp class String { public: String(int); // BAD // ... }; String s = 10; // surprise: string of size 10 ``` -------------------------------- ### C++ Unused Parameter Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index An example illustrating how to handle unused parameters in C++ function declarations. Unused parameters should be unnamed to improve readability and suppress compiler warnings. ```cpp widget* find(const set& s, const widget& w, Hint); // once upon a time, a hint was used ``` -------------------------------- ### C++: Conventional const usage Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ example demonstrates the preferred conventional use of `const` for variables and pointers. It contrasts 'OK' examples (`const int x = 7;`) with 'bad' examples (`int const y = 9;`) and 'OK' pointer usage (`const int *const p = nullptr;`) versus 'bad' (`int const *const p = nullptr;`), emphasizing familiarity and consistency. ```cpp const int x = 7; // OK int const y = 9; // bad const int *const p = nullptr; // OK, constant pointer to constant int int const *const p = nullptr; // bad, constant pointer to constant int ``` -------------------------------- ### RAII for File Handling in C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the correct way to manage file resources using RAII with `std::ifstream`. It contrasts this with manual management using `FILE*` and `fopen`/`fclose`, highlighting potential leaks when exceptions or early returns occur. ```C++ void f(int i) { FILE* f = fopen("a file", "r"); ifstream is { "another file" }; // ... if (i == 0) return; // Potential leak of 'f' // ... fclose(f); } ``` ```C++ void f(int i) { unique_ptr f(fopen("a file", "r"), fclose); // ... if (i == 0) return; // ... } ``` ```C++ void f(int i) { ifstream input {"a file"}; // ... if (i == 0) return; // ... } ``` -------------------------------- ### C++ Variable Re-use Example (Bad Practice) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Provides a detrimental example where a single variable `i` is reused for two distinct loop iterations, compromising code readability and potentially leading to errors. ```cpp void use() { int i; for (i = 0; i < 20; ++i) { /* ... */ } for (i = 0; i < 200; ++i) { /* ... */ } // bad: i recycled } ``` -------------------------------- ### State Intent Clearly in C++ Comments Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This example shows how to use comments to explain the intent or purpose of a function, especially when the implementation is complex. Good comments clarify the 'what' and 'why' of the code's behavior. ```c++ void stable_sort(Sortable& c) // sort c in the order determined by <, keep equal elements (as defined by ==) in // their original relative order { // ... quite a few lines of non-trivial code ... } ``` -------------------------------- ### C++: Efficient Initialization with Initializers and Lambdas Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Shows advanced C++ techniques for efficient object initialization, especially for expensive types. It demonstrates using initializer lists in functions and C++17 structured bindings with lambdas to manage initialization logic and avoid redundant assignments. ```cpp pair make_related_widgets(bool x) { return (x) ? {f1(), f2()} : {f3(), f4()}; } auto [i, j] = make_related_widgets(cond); // C++17 ``` ```cpp auto [i, j] = [x] { return (x) ? pair{f1(), f2()} : pair{f3(), f4()} }(); // C++17 ``` -------------------------------- ### Class X3 with Default Constructor Arguments - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index An 'Alternative' example using class 'X3' with default arguments for constructor parameters. This approach is less explicit and can lead to repetitive code and overhead compared to default member initializers. ```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 // ... }; ``` -------------------------------- ### C++ Template Pair Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A simple C++ template struct 'pair' with public members 'a' and 'b'. This example highlights that arbitrary users can independently modify these members, which might be undesirable if specific invariants need to be enforced. ```cpp template struct pair { T a; U b; // ... }; ``` -------------------------------- ### C qsort Usage Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This example demonstrates how to use the C qsort function to sort an array of doubles. It requires explicitly specifying the array, the number of elements, the size of each element (sizeof(double)), and a comparison function (compare_doubles). ```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); ``` -------------------------------- ### C++ Virtual Function Calls in Constructors (Bad Example) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates a potentially problematic scenario in C++ where virtual functions are called within a constructor. This example shows why such calls can lead to unexpected behavior or undefined behavior if pure virtual functions are called. ```cpp class Base { public: virtual void f() = 0; // not implemented virtual void g(); // implemented with Base version virtual void h(); // implemented with Base version virtual ~Base(); // implemented with Base version }; class Derived : public Base { public: void g() override; // provide Derived implementation void h() final; // provide Derived implementation Derived() { // BAD: attempt to call an unimplemented virtual function f(); // BAD: will call Derived::g, not dispatch further virtually g(); // GOOD: explicitly state intent to call only the visible version Derived::g(); // ok, no qualification needed, h is final h(); } }; ``` -------------------------------- ### RAII for Resource Management in C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the Resource Acquisition Is Initialization (RAII) idiom for automatic resource management. It shows how to wrap resources like file handles or locks in classes with destructors to ensure cleanup, even in the presence of exceptions. This avoids manual cleanup code and potential leaks. ```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; } class Port { PortHandle port; public: Port(string_view destination) : port{open_port(destination)} { } ~Port() { close_port(port); } operator PortHandle() { return port; } // port handles can't usually be cloned, so disable copying and assignment if necessary Port(const Port&) = delete; Port& operator=(const Port&) = delete; }; void send(unique_ptr x, string_view destination) // x owns the X { Port port{destination}; // port owns the PortHandle lock_guard guard{my_mutex}; // guard owns the lock // ... send(port, x); // ... } // automatically unlocks my_mutex and deletes the pointer in x ``` -------------------------------- ### Exception Handling Example with Vectors and File Handles Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates how constructors for types like `vector`, `string`, and custom handles (`File_handle`) can throw exceptions upon failure to allocate memory, copy elements, or open files. This allows calling code to handle errors gracefully, ensuring proper cleanup of constructed members. ```cpp struct Foo { vector v; File_handle f; string s; }; void use() { Foo bar { {Thing{1}, Thing{2}, Thing{monkey} }, {"my_file", "r"}, "Here we go!"}; // ... } ``` ```cpp File_handle::File_handle(const string& name, const string& mode) : f{fopen(name.c_str(), mode.c_str())} { if (!f) throw runtime_error{"File_handle: could not open " + name + " as " + mode}; } ``` -------------------------------- ### C++ Pointer Lifetime and Dereference Example Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Shows an example of dereferencing a pointer that might become invalid due to scope changes within conditional blocks. The corrected version demonstrates extending the lifetime of the pointed-to objects or ensuring the pointer is valid at the point of dereference. ```cpp void f() { int x = 0; int* p = &x; if (condition()) { int y = 0; p = &y; } // invalidates p *p = 42; // BAD, p might be invalid if the branch was taken } void f1() { int x = 0; int* p = &x; int y = 0; if (condition()) { p = &y; } *p = 42; // OK, p points to x or y and both are still in scope } ``` -------------------------------- ### Input Stream Initialization and Ownership (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates initializing an input stream pointer based on different sources (stdin, command line, file) and managing its ownership. It highlights potential issues with uninitialized variables, ownership violations, and the need for manual memory management. ```cpp bool owned; owner inp; switch (source) { case std_in: owned = false; inp = &cin; break; case command_line: owned = true; inp = new istringstream{argv[2]}; break; case file: owned = true; inp = new ifstream{argv[2]}; break; } istream& in = *inp; if (owned) delete inp; ``` -------------------------------- ### Use Standard Algorithms (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates the use of standard library algorithms like 'accumulate' for common operations. It contrasts the concise and efficient use of algorithms with manual loop implementations, highlighting that well-known algorithms should be preferred over custom, verbose code. This promotes readability and reduces potential errors. ```C++ auto sum = accumulate(begin(a), end(a), 0.0); // good a range version of `accumulate` would be even better: auto sum = accumulate(v, 0.0); // better ``` ```C++ int max = v.size(); // bad: verbose, purpose unstated double sum = 0.0; for (int i = 0; i < max; ++i) sum = sum + v[i]; ``` -------------------------------- ### Overconstrained Sum Algorithm Examples (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates conceptually incorrect or overconstrained generic function templates. sum1 requires only Incrementable, while sum2 requires Simple_number. These examples highlight the risks of overly specific constraints that might miss generalization opportunities or exclude valid types. ```cpp template requires Incrementable T sum1(vector& v, T s) { for (auto x : v) s += x; return s; } template requires Simple_number T sum2(vector& v, T s) { for (auto x : v) s = s + x; return s; } ``` -------------------------------- ### Example of a poorly designed function (Don't) - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This example demonstrates a function that violates several principles, such as performing multiple logical operations (reading, writing, error handling) and having tightly coupled dependencies on specific output streams. It illustrates the negative consequences of not factoring out distinct operations. ```cpp void read_and_print(istream& is) // read and print an int { int x; if (is >> x) cout << "the int is " << x << '\n'; else cerr << "no int on input\n"; } ``` -------------------------------- ### Aggregate Headers for Convenience Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the concept of creating a single header file ('basic_std_lib.h') that includes a set of commonly used standard library headers. This allows users to include a single file to gain access to multiple declarations. ```cpp // basic_std_lib.h: #include #include #include #include #include ``` ```cpp #include "basic_std_lib.h" ``` -------------------------------- ### Internal Entities with Unnamed Namespaces - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the correct way to use unnamed (anonymous) namespaces for internal, non-exported entities in implementation source files. The 'bad' example uses `static` for internal linkage, while the 'good' example effectively achieves the same by placing these declarations within an unnamed namespace. ```cpp // bad example static int f(); int g(); static bool h(); int k(); // good example namespace { int f(); bool h(); } int g(); int k(); ``` -------------------------------- ### C++ Core Guidelines: Constructor Usage Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This snippet provides guidance on constructor usage in C++, focusing on maintaining invariants, handling exceptions (`throw`), default constructors, and the use of `explicit` constructors. It also covers delegating constructors and virtual constructors. ```c++ // constructor: invariant – establish invariant – `throw` – default – not needed – `explicit` – delegating – `virtual` ``` -------------------------------- ### C++ Union Type Punning Example (Bad Practice) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ code demonstrates a dangerous use of `union` for type punning, which leads to undefined behavior. It shows how attempting to access a `union` member with a different type than the one last written can cause issues. The example highlights why this practice is discouraged. ```cpp union Pun { int x; unsigned char c[sizeof(int)]; }; void bad(Pun& u) { u.x = 'x'; cout << u.c[0] << '\n'; // undefined behavior } ``` -------------------------------- ### RAII for Resource Management Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates the Resource Acquisition Is Initialization (RAII) principle in C++. It shows how to encapsulate resource management within a class constructor and destructor to prevent leaks. ```cpp // Example demonstrating RAII principle: // Acquire resource in constructor, release in destructor. class ResourceManager { public: ResourceManager() { // Acquire resource (e.g., open file, allocate memory) } ~ResourceManager() { // Release resource (e.g., close file, deallocate memory) } // ... other methods ... }; ``` -------------------------------- ### Class X2 with Default Member Initializers - C++ Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index A 'GOOD' example using class 'X2' which utilizes default member initializers for all members. Constructors either use the default or explicitly initialize specific members, ensuring consistent defaults. ```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 // ... }; ``` -------------------------------- ### Preventing Resource Leaks with Exceptions Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Demonstrates how to avoid resource leaks when exceptions are thrown. The first example shows a potential leak with manual memory management (`new`/`delete`). The subsequent examples show how `std::make_unique` and RAII (via `std::vector`) automatically manage resource cleanup, even when exceptions occur. ```cpp void leak(int x) // don't: might leak { auto p = new int{7}; if (x < 0) throw Get_me_out_of_here{}; // might leak *p // ... delete p; // we might never get here } ``` ```cpp void no_leak(int x) { auto p = make_unique(7); if (x < 0) throw Get_me_out_of_here{}; // will delete *p if necessary // ... // no need for delete p } ``` ```cpp void no_leak_simplified(int x) { vector v(7); // ... } ``` -------------------------------- ### Avoid Holding Locks Across Coroutine Suspension (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ example demonstrates the danger of holding a std::lock_guard across a coroutine suspension point (co_await). Holding a lock during suspension can lead to deadlocks or undefined behavior if the coroutine resumes on a different thread. The 'good' example shows releasing the lock before suspension. ```cpp std::mutex g_lock; std::future Class::do_something() { std::lock_guard guard(g_lock); co_await something(); // DANGER: coroutine has suspended execution while holding a lock co_await somethingElse(); } ``` ```cpp std::mutex g_lock; std::future Class::do_something() { { std::lock_guard guard(g_lock); // modify data protected by lock } co_await something(); // OK: lock has been released before coroutine suspends co_await somethingElse(); } ``` -------------------------------- ### C++ Abstract Device Interface with Concrete Implementations Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Presents an abstract base class `Device` used as an interface for hardware devices. It defines pure virtual `write` and `read` methods. Concrete classes `D1` and `D2` provide specific implementations, allowing interchangeable use through the `Device` interface. ```cpp struct Device { virtual ~Device() = default; virtual void write(span outbuf) = 0; virtual void read(span inbuf) = 0; }; class D1 : public Device { // ... data ... void write(span outbuf) override; void read(span inbuf) override; }; class D2 : public Device { // ... different data ... void write(span outbuf) override; void read(span inbuf) override; }; ``` -------------------------------- ### C.21 Bad Example: Incomplete Special Member Functions Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ code snippet demonstrates a 'bad' example for the Rule of Five (C.21). The 'M2' struct defines a destructor that handles memory deallocation but omits all copy and move operations. This can lead to issues like double deletion if default copy assignment is used. ```cpp struct M2 { // bad: incomplete set of copy/move/destructor operations public: // ... // ... no copy or move operations ... ~M2() { delete[] rep; } private: pair* rep; // zero-terminated set of pairs }; void use() { M2 x; M2 y; // ... x = y; // the default assignment // ... } ``` -------------------------------- ### Loop for Finding Element (C++) Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Illustrates a 'bad' C-style loop for finding an element in a vector, highlighting potential issues and suggesting a better 'good' approach using `std::find`. This promotes using standard library algorithms for clearer intent and robustness. The 'bad' example also notes the preference for `gsl::index`. ```cpp void f(vector& v) { string val; cin >> val; // ... int index = -1; // bad, plus should use gsl::index for (int i = 0; i < v.size(); ++i) { if (v[i] == val) { index = i; break; } } // ... } ``` ```cpp void f(vector& v) { string val; cin >> val; // ... auto p = find(begin(v), end(v), val); // better // ... } ``` -------------------------------- ### C++ Initialization Syntax in Templates Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index Shows various initialization syntaxes within a C++ template function, including value initialization, direct initialization, and default initialization, contrasting them with function declarations. ```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.21 Good Example: Explicitly Defined Special Member Functions Source: https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines.html/index This C++ code snippet provides a 'good' example of the Rule of Five (C.21) by explicitly defining all special member functions: destructor, copy constructor, copy assignment, move constructor, and move assignment. Using `= default` signifies intentional default behavior for each. ```cpp class X { public: // ... virtual ~X() = default; // destructor (virtual if X is meant to be a base class) X(const X&) = default; // copy constructor X& operator=(const X&) = default; // copy assignment X(X&&) noexcept = default; // move constructor X& operator=(X&&) noexcept = default; // move assignment }; ```