├── .github └── FUNDING.yml ├── 00-Table_of_Contents.md ├── 01-Preface.md ├── 02-Use_the_Tools_Available.md ├── 03-Style.md ├── 04-Considering_Safety.md ├── 05-Considering_Maintainability.md ├── 06-Considering_Portability.md ├── 07-Considering_Threadability.md ├── 08-Considering_Performance.md ├── 09-Considering_Correctness.md ├── 10-Enable_Scripting.md ├── 11-Further_Reading.md ├── 12-Final_Thoughts.md ├── LICENSE ├── README.md ├── SUMMARY.md ├── Sorting in C vs C++.pdf └── book.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: lefticus 4 | patreon: lefticus 5 | -------------------------------------------------------------------------------- /00-Table_of_Contents.md: -------------------------------------------------------------------------------- 1 | 2 | 1. [Preface](01-Preface.md) 3 | 2. [Use the Tools Available](02-Use_the_Tools_Available.md) 4 | 3. [Style](03-Style.md) 5 | 4. [Considering Safety](04-Considering_Safety.md) 6 | 5. [Considering Maintainability](05-Considering_Maintainability.md) 7 | 6. [Considering Portability](06-Considering_Portability.md) 8 | 7. [Considering Threadability](07-Considering_Threadability.md) 9 | 8. [Considering Performance](08-Considering_Performance.md) 10 | 9. [Considering Correctness](09-Considering_Correctness.md) 11 | 10. [Enable Scripting](10-Enable_Scripting.md) 12 | 11. [Further Reading](11-Further_Reading.md) 13 | 12. [Final Thoughts](12-Final_Thoughts.md) 14 | -------------------------------------------------------------------------------- /01-Preface.md: -------------------------------------------------------------------------------- 1 | # Preface 2 | 3 | C++ Best Practices: A Forkable Coding Standards Document 4 | 5 | This document is meant to be a collaborative discussion of the best practices in C++. It complements books such as *Effective C++* (Meyers) and *C++ Coding Standards* (Alexandrescu, Sutter). We fill in some of the lower level details that they don't discuss and provide specific stylistic recommendations while also discussing how to ensure overall code quality. 6 | 7 | In all cases brevity and succinctness is preferred. Examples are preferred for making the case for why one option is preferred over another. If necessary, words will be used. 8 | 9 | 10 | Creative Commons License
C++ Best Practices by Jason Turner is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License. 11 | 12 | *Disclaimer* 13 | 14 | This document is based on my personal experiences. You are not supposed to agree with it 100%. It exists as a book on [GitHub](https://github.com/lefticus/cppbestpractices) so that you can fork it for your own uses or submit back proposed changes for everyone to share. 15 | 16 | This book has inspired an O'Reilly video: [Learning C++ Best Practices](http://shop.oreilly.com/product/0636920049814.do) 17 | -------------------------------------------------------------------------------- /02-Use_the_Tools_Available.md: -------------------------------------------------------------------------------- 1 | # Use The Tools Available 2 | 3 | An automated framework for executing these tools should be established very early in the development process. It should not take more than 2-3 commands to checkout the source code, build, and execute the tests. Once the tests are done executing, you should have an almost complete picture of the state and quality of the code. 4 | 5 | ## Source Control 6 | 7 | Source control is an absolute necessity for any software development project. If you are not using one yet, start using one. 8 | 9 | * [GitHub](https://github.com/) - allows for unlimited public repositories, and unlimited private repositories with up to 3 collaborators. 10 | * [Bitbucket](https://bitbucket.org/) - allows for unlimited private repositories with up to 5 collaborators, for free. 11 | * [SourceForge](http://sourceforge.net/) - open source hosting only. 12 | * [GitLab](https://gitlab.com/) - allows for unlimited public and private repositories, unlimited CI Runners included, for free. 13 | * [Visual Studio Online](https://visualstudio.com) (http://www.visualstudio.com/what-is-visual-studio-online-vs) - allows for unlimited public repositories, must pay for private repository. Repositories can be git or TFVC. Additionally: Issue tracking, project planning (multiple Agile templates, such as SCRUM), integrated hosted builds, integration of all this into Microsoft Visual Studio. Windows only. 14 | 15 | ## Build Tool 16 | 17 | Use an industry standard widely accepted build tool. This prevents you from reinventing the wheel whenever you discover / link to a new library / package your product / etc. Examples include: 18 | 19 | * [Autotools](https://autotools.io) - The traditional GNU build system. 20 | * [CMake](http://www.cmake.org/) 21 | * Consider: https://github.com/sakra/cotire/ for build performance 22 | * Consider: https://github.com/toeb/cmakepp for enhanced usability 23 | * Utilize: https://cmake.org/cmake/help/v3.6/command/target_compile_features.html for C++ standard flags 24 | * Consider: https://github.com/cheshirekow/cmake_format for automatic formatting of your CMakeLists.txt 25 | * See the [Further Reading](11-Further_Reading.md) section for CMake specific best practices 26 | * `cmake --build` provides a common interface for compiling your project regardless of platform 27 | * [Waf](https://waf.io/) 28 | * [FASTBuild](http://www.fastbuild.org/) 29 | * [Ninja](https://ninja-build.org/) - Can greatly improve the incremental build time of your larger projects. Can be used as a target for CMake. 30 | * [Bazel](http://bazel.io/) - Fast incremental builds using network artifact caching and remote execution. 31 | * [Buck](http://buckbuild.com/) - Similar to Bazel, with very good support for iOS and Android. 32 | * [gyp](https://chromium.googlesource.com/external/gyp/) - Google's build tool for chromium. 33 | * [maiken](https://github.com/Dekken/maiken) - Crossplatform build tool with Maven-esque configuration style. 34 | * [Qt Build Suite](http://doc.qt.io/qbs/) - Crossplatform build tool From Qt. 35 | * [meson](http://mesonbuild.com/index.html) - Open source build system meant to be both extremely fast, and, even more importantly, as user-friendly as possible. 36 | * [premake](https://premake.github.io/) 37 | * [xmake](https://xmake.io) - A cross-platform build utility based on Lua. Modern C/C++ build tools, Support multi-language hybrid compilation 38 | * [build2](https://build2.org) - A cargo-like complete toolchain (build system, package manager, project manager) 39 | 40 | Remember, it's not just a build tool, it's also a programming language. Try to maintain good clean build scripts and follow the recommended practices for the tool you are using. 41 | 42 | ## Package Manager 43 | 44 | Package management is an important topic in C++, with currently no clear winner. Consider using a package manager to help you keep track of the dependencies for your project and make it easier for new people to get started with the project. 45 | 46 | * [Conan](https://www.conan.io/) - a crossplatform dependency manager for C++ 47 | * [hunter](https://github.com/ruslo/hunter) - CMake driven cross-platform package manager for C/C++ 48 | * [C++ Archive Network (CPPAN)](https://cppan.org/) - a crossplatform dependency manager for C++ 49 | * [qpm](https://www.qpm.io/) - Package manager for Qt 50 | * [build2](https://build2.org/) - A cargo-like complete toolchain (build system, package manager, project manager) 51 | * [Buckaroo](https://buckaroo.pm) - Truly decentralized cross-platform dependency manager for C/C++ and more 52 | * [Vcpkg](https://github.com/microsoft/vcpkg) - Microsoft C++ Library Manager for Windows, Linux, and macOS - [description](https://docs.microsoft.com/en-us/cpp/build/vcpkg) 53 | * [CPM](https://github.com/cpm-cmake/CPM.cmake) - CMake package manager for modern CMake 54 | 55 | ## Continuous Integration 56 | 57 | Once you have picked your build tool, set up a continuous integration environment. 58 | 59 | Continuous Integration (CI) tools automatically build the source code as changes are pushed to the repository. These can be hosted privately or with a CI host. 60 | 61 | * [Travis CI](http://travis-ci.org) 62 | * works well with C++ 63 | * designed for use with GitHub 64 | * free for public repositories on GitHub 65 | * [AppVeyor](http://www.appveyor.com/) 66 | * supports Windows, MSVC and MinGW 67 | * free for public repositories on GitHub 68 | * [Hudson CI](http://hudson-ci.org/) / [Jenkins CI](https://jenkins-ci.org/) 69 | * Java Application Server is required 70 | * supports Windows, OS X, and Linux 71 | * extendable with a lot of plugins 72 | * [TeamCity](https://www.jetbrains.com/teamcity) 73 | * has a free option for open source projects 74 | * [Decent CI](https://github.com/lefticus/decent_ci) 75 | * simple ad-hoc continuous integration that posts results to GitHub 76 | * supports Windows, OS X, and Linux 77 | * used by [ChaiScript](http://chaiscript.com/ChaiScript-BuildResults/full_dashboard.html) 78 | * [Visual Studio Online](https://visualstudio.com) (http://www.visualstudio.com/what-is-visual-studio-online-vs) 79 | * Tightly integrated with the source repositories from Visual Studio Online 80 | * Uses MSBuild (Visual Studio's build engine), which is available on Windows, OS X and Linux 81 | * Provides hosted build agents and also allows for user-provided build agents 82 | * Can be controlled and monitored from within Microsoft Visual Studio 83 | * On-Premise installation via Microsoft Team Foundation Server 84 | * [GitLab](https://gitlab.com) 85 | * use custom Docker images, so can be used for C++ 86 | * has free shared runners 87 | * has trivial processing of result of coverage analyze 88 | 89 | If you have an open source, publicly-hosted project on GitHub: 90 | 91 | * go enable github actions. A template for this can be found in the [C++ Boilerplate Template](https://github.com/cpp-best-practices/cmake_conan_boilerplate_template) 92 | * enable one of the coverage tools listed below (Codecov or Coveralls) 93 | * enable [Coverity Scan](https://scan.coverity.com) 94 | 95 | These tools are all free and relatively easy to set up. Once they are set up you are getting continuous building, testing, analysis and reporting of your project. For free. 96 | 97 | 98 | ## Compilers 99 | 100 | Use every available and reasonable set of warning options. Some warning options only work with optimizations enabled, or work better the higher the chosen level of optimization is, for example [`-Wnull-dereference`](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wnull-dereference-367) with GCC. 101 | 102 | You should use as many compilers as you can for your platform(s). Each compiler implements the standard slightly differently and supporting multiple will help ensure the most portable, most reliable code. 103 | 104 | ### GCC / Clang 105 | 106 | `-Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic` - use these and consider the following (see descriptions below) 107 | 108 | * `-pedantic` - Warn on language extensions 109 | * `-Wall -Wextra` reasonable and standard 110 | * `-Wshadow` warn the user if a variable declaration shadows one from a parent context 111 | * `-Wnon-virtual-dtor` warn the user if a class with virtual functions has a non-virtual destructor. This helps catch hard to track down memory errors 112 | * `-Wold-style-cast` warn for c-style casts 113 | * `-Wcast-align` warn for potential performance problem casts 114 | * `-Wunused` warn on anything being unused 115 | * `-Woverloaded-virtual` warn if you overload (not override) a virtual function 116 | * `-Wpedantic` (all versions of GCC, Clang >= 3.2) warn if non-standard C++ is used 117 | * `-Wconversion` warn on type conversions that may lose data 118 | * `-Wsign-conversion` (Clang all versions, GCC >= 4.3) warn on sign conversions 119 | * `-Wmisleading-indentation` (only in GCC >= 6.0) warn if indentation implies blocks where blocks do not exist 120 | * `-Wduplicated-cond` (only in GCC >= 6.0) warn if `if` / `else` chain has duplicated conditions 121 | * `-Wduplicated-branches` (only in GCC >= 7.0) warn if `if` / `else` branches have duplicated code 122 | * `-Wlogical-op` (only in GCC) warn about logical operations being used where bitwise were probably wanted 123 | * `-Wnull-dereference` (only in GCC >= 6.0) warn if a null dereference is detected 124 | * `-Wuseless-cast` (only in GCC >= 4.8) warn if you perform a cast to the same type 125 | * `-Wdouble-promotion` (GCC >= 4.6, Clang >= 3.8) warn if `float` is implicitly promoted to `double` 126 | * `-Wformat=2` warn on security issues around functions that format output (i.e., `printf`) 127 | * `-Wlifetime` (only special branch of Clang currently) shows object lifetime issues 128 | * `-Wimplicit-fallthrough` Warns when case statements fall-through. (Included with `-Wextra` in GCC, not in clang) 129 | 130 | Consider using `-Weverything` and disabling the few warnings you need to on Clang 131 | 132 | 133 | `-Weffc++` warning mode can be too noisy, but if it works for your project, use it also. 134 | 135 | ### MSVC 136 | 137 | `/permissive-` - [Enforces standards conformance](https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance). 138 | 139 | `/W4 /w14640` - use these and consider the following (see descriptions below) 140 | 141 | * `/W4` All reasonable warnings 142 | * `/w14242` 'identfier': conversion from 'type1' to 'type1', possible loss of data 143 | * `/w14254` 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data 144 | * `/w14263` 'function': member function does not override any base class virtual member function 145 | * `/w14265` 'classname': class has virtual functions, but destructor is not virtual instances of this class may not be destructed correctly 146 | * `/w14287` 'operator': unsigned/negative constant mismatch 147 | * `/we4289` nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside the for-loop scope 148 | * `/w14296` 'operator': expression is always 'boolean_value' 149 | * `/w14311` 'variable': pointer truncation from 'type1' to 'type2' 150 | * `/w14545` expression before comma evaluates to a function which is missing an argument list 151 | * `/w14546` function call before comma missing argument list 152 | * `/w14547` 'operator': operator before comma has no effect; expected operator with side-effect 153 | * `/w14549` 'operator': operator before comma has no effect; did you intend 'operator'? 154 | * `/w14555` expression has no effect; expected expression with side-effect 155 | * `/w14619` pragma warning: there is no warning number 'number' 156 | * `/w14640` Enable warning on thread unsafe static member initialization 157 | * `/w14826` Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. 158 | * `/w14905` wide string literal cast to 'LPSTR' 159 | * `/w14906` string literal cast to 'LPWSTR' 160 | * `/w14928` illegal copy-initialization; more than one user-defined conversion has been implicitly applied 161 | 162 | Not recommended 163 | 164 | * `/Wall` - Not recommended for normal builds because the MSVC standard library is not `/Wall` "clean", but can be enabled to discover new warnings to enable. 165 | * Since VS2022, `/external:anglebrackets /external:W0` can be used to turn off warnings from all headers included with angle brackets, e.g. `#include `. 166 | 167 | 168 | 169 | ### General 170 | 171 | Start with very strict warning settings from the beginning. Trying to raise the warning level after the project is underway can be painful. 172 | 173 | Consider using the *treat warnings as errors* setting. `/WX` with MSVC, `-Werror` with GCC / Clang 174 | 175 | ## LLVM-based tools 176 | 177 | LLVM based tools work best with a build system (such as cmake) that can output a compile command database, for example: 178 | 179 | ``` 180 | $ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON . 181 | ``` 182 | 183 | If you are not using a build system like that, you can consider [Build EAR](https://github.com/rizsotto/Bear) which will hook into your build system and generate a compile command database for you. 184 | 185 | CMake now also comes with built-in support for calling `clang-tidy` during [normal compilation](https://cmake.org/cmake/help/latest/prop_tgt/LANG_CLANG_TIDY.html). 186 | 187 | * [include-what-you-use](https://github.com/include-what-you-use), [example results](https://github.com/ChaiScript/ChaiScript/commit/c0bf6ee99dac14a19530179874f6c95255fde173) 188 | * [clang-check](http://clang.llvm.org/docs/ClangCheck.html) 189 | * [clang-tidy](http://clang.llvm.org/extra/clang-tidy.html) 190 | 191 | ## Static Analyzers 192 | 193 | The best bet is the static analyzer that you can run as part of your automated build system. Cppcheck and clang meet that requirement for free options. 194 | 195 | ### SonarLint / SonarQube / SonarCloud 196 | 197 | [SonarLint](https://www.sonarsource.com/products/sonarlint/) runs as a plug-in in all the main IDEs. The other two run as part of your build pipeline and can also gate PRs. [SonarQube](https://www.sonarsource.com/products/sonarqube/) runs on your own infrastructure whereas [SonarCloud](https://www.sonarsource.com/products/sonarcloud/) runs in The Cloud, is free for public Open Source projects and supports Automatic Analysis for zero-config setup. 198 | 199 | All three run the same set of analyzers (although SonarQube and SonarCloud have a handful of additional checks that are too heavyweight to run in-IDE) that catch code smells and best practice violations, as well as complex bugs. 200 | 201 | ### Coverity Scan 202 | 203 | [Coverity](https://scan.coverity.com/) has a free (for open source) static analysis toolkit that can work on every commit in integration with [Travis CI](http://travis-ci.org) and [AppVeyor](http://www.appveyor.com/). 204 | 205 | ### PVS-Studio 206 | 207 | [PVS-Studio](http://www.viva64.com/en/pvs-studio/) is a tool for bug detection in the source code of programs, written in C, C++ and C#. It is free for personal academic projects, open source non-commercial projects and independent projects of individual developers. It works in Windows and Linux environment. 208 | 209 | ### Cppcheck 210 | [Cppcheck](http://cppcheck.sourceforge.net/) is free and open source. It strives for 0 false positives and does a good job at it. Therefore all warnings should be enabled: `--enable=all` 211 | 212 | Notes: 213 | 214 | * For correct work it requires well formed path for headers, so before usage don't forget to pass: `--check-config`. 215 | * Finding unused headers does not work with `-j` more than 1. 216 | * Remember to add `--force` for code with a lot number of `#ifdef` if you need to check all of them. 217 | 218 | ### cppclean 219 | 220 | [cppclean](https://github.com/myint/cppclean) - Open source static analyzer focused on finding problems in C++ source that slow development of large code bases. 221 | 222 | 223 | ### CppDepend 224 | 225 | [CppDepend](https://www.cppdepend.com/) Simplifies managing a complex C/C++ code base by analyzing and visualizing code dependencies, by defining design rules, by doing impact analysis, and comparing different versions of the code. It's free for OSS contributors. 226 | 227 | ### Clang's Static Analyzer 228 | 229 | Clang's analyzer's default options are good for the respective platform. It can be used directly [from CMake](http://garykramlich.blogspot.com/2011/10/using-scan-build-from-clang-with-cmake.html). They can also be called via clang-check and clang-tidy from the [LLVM-based Tools](#llvm-based-tools). 230 | 231 | Also, [CodeChecker](https://github.com/Ericsson/CodeChecker) is available as a front-end to clang's static analysis. 232 | 233 | `clang-tidy` can be easily used with Visual Studio via the [Clang Power Tools](https://clangpowertools.com) extension. 234 | 235 | ### MSVC's Static Analyzer 236 | 237 | Can be enabled with the `/analyze` [command line option](http://msdn.microsoft.com/en-us/library/ms173498.aspx). For now we will stick with the default options. 238 | 239 | ### Flint / Flint++ 240 | 241 | [Flint](https://github.com/facebook/flint) and [Flint++](https://github.com/L2Program/FlintPlusPlus) are linters that analyze C++ code against Facebook's coding standards. 242 | 243 | ### OCLint 244 | 245 | [OCLint](http://oclint.org/) is a free, libre and open source static code analysis tool for improving quality of C++ code in many different ways. 246 | 247 | ### ReSharper C++ / CLion 248 | 249 | Both of these tools from [JetBrains](https://www.jetbrains.com/cpp/) offer some level of static analysis and automated fixes for common things that can be done better. They have options available for free licenses for open source project leaders. 250 | 251 | ### Cevelop 252 | 253 | The Eclipse based [Cevelop](https://www.cevelop.com/) IDE has various static analysis and refactoring / code fix tools available. For example, you can replace macros with C++ `constexprs`, refactor namespaces (extract/inline `using`, qualify name), and refactor your code to C++11's uniform initialization syntax. Cevelop is free to use. 254 | 255 | ### Qt Creator 256 | 257 | Qt Creator can plug into the clang static analyzer. 258 | 259 | ### clazy 260 | 261 | [clazy](https://github.com/KDE/clazy) is a clang based tool for analyzing Qt usage. 262 | 263 | ### IKOS 264 | 265 | [IKOS](https://ti.arc.nasa.gov/opensource/ikos/) is an open source static analyzer, developed by NASA. It is based on the Abstract Interpretation. It is written in C++ and provides an analyzer for C and C++, using LLVM. 266 | The source code is [available on GitHub](https://github.com/NASA-SW-VnV/ikos). 267 | 268 | ### codespell 269 | 270 | [codespell](https://github.com/codespell-project/codespell) is a spell checker for your source code. 271 | 272 | ## Runtime Checkers 273 | 274 | ### Code Coverage Analysis 275 | 276 | A coverage analysis tool shall be run when tests are executed to make sure the entire application is being tested. Unfortunately, coverage analysis requires that compiler optimizations be disabled. This can result in significantly longer test execution times. 277 | 278 | * [Codecov](https://codecov.io/) 279 | * integrates with Travis CI and AppVeyor 280 | * free for open source projects 281 | * [Coveralls](https://coveralls.io/) 282 | * integrates with Travis CI and AppVeyor 283 | * free for open source projects 284 | * [LCOV](http://ltp.sourceforge.net/coverage/lcov.php) 285 | * very configurable 286 | * [Gcovr](http://gcovr.com/) 287 | * [kcov](http://simonkagstrom.github.io/kcov/index.html) 288 | * integrates with codecov and coveralls 289 | * performs code coverage reporting without needing special compiler flags, just by instrumenting debug symbols. 290 | * [OpenCppCoverage](https://github.com/OpenCppCoverage/OpenCppCoverage) - open source coverage reporting tool for Windows. 291 | 292 | 293 | ### Heap profiling 294 | 295 | * [Valgrind](http://www.valgrind.org/) 296 | * Valgrind is a runtime code analyzer that can detect memory leaks, race conditions, and other associated problems. It is supported on various Unix platforms. 297 | * [Heaptrack](https://github.com/KDE/heaptrack) 298 | * A profiler created by a Valgrind's Massif developer. Quite similar to Massif with pros and cons over it, way more intuitive though. 299 | * [Dr Memory](http://www.drmemory.org) 300 | * [Memoro](https://epfl-vlsc.github.io/memoro/) - A detailed heap profiler. 301 | 302 | ### CPU profiling 303 | 304 | * [Hotspot](https://github.com/KDAB/hotspot) - An intuitive front-end to visualize datas produced by the [perf](https://perf.wiki.kernel.org) CPU profiler. 305 | * [uftrace](https://github.com/namhyung/uftrace) - Can be used to generating function call graphs of a program execution. 306 | 307 | ### Reverse engineering tools 308 | 309 | * [Cutter](https://cutter.re/) - A front-end for [Radare2](https://www.radare.org/n/radare2.html). It provides tools such as decompiler, disassembly, graph visualizer, hex editor. 310 | * [Ghidra](https://ghidra-sre.org/) - Ghidra is a free and open source reverse engineering tool developed by the National Security Agency (NSA) of the United States. 311 | 312 | ### GCC / Clang Sanitizers 313 | 314 | These tools provide many of the same features as Valgrind, but built into the compiler. They are easy to use and provide a report of what went wrong. 315 | 316 | * AddressSanitizer 317 | * MemorySanitizer 318 | * ThreadSanitizer 319 | * UndefinedBehaviorSanitizer 320 | 321 | Be aware of the sanitizer options available, including runtime options. https://kristerw.blogspot.com/2018/06/useful-gcc-address-sanitizer-checks-not.html 322 | 323 | ### Fuzzy Analyzers 324 | 325 | If your project accepts user defined input, considering running a fuzzy input tester. 326 | 327 | Both of these tools use coverage reporting to find new code execution paths and try to breed novel inputs for your code. They can find crashes, hangs, and inputs you didn't know were considered valid. 328 | 329 | * [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) 330 | * [LibFuzzer](http://llvm.org/docs/LibFuzzer.html) 331 | * [KLEE](http://klee.github.io/) - Can be used to fuzz individual functions 332 | 333 | #### Continuous Fuzzing 334 | 335 | Continuous fuzzing tools exist to run fuzz tests for you with each commit. 336 | 337 | * [Fuzzit](https://fuzzit.dev/) 338 | 339 | ### Mutation Testers 340 | 341 | These tools take code executed during unit test runs and mutate the executed code. If the test continues to pass with a mutation in place, then there is likely a flawed test in your suite. 342 | 343 | * [Dextool Mutate](https://github.com/joakim-brannstrom/dextool/tree/master/plugin/mutate) 344 | * [MuCPP](https://neptuno.uca.es/redmine/projects/mucpp-mutation-tool/wiki) 345 | * [mull](https://github.com/mull-project/mull) 346 | * [CCMutator](https://github.com/markus-kusano/CCMutator) 347 | * [Universal Mutator](https://github.com/agroce/universalmutator) 348 | 349 | ### Control Flow Guard 350 | 351 | MSVC's [Control Flow Guard](https://msdn.microsoft.com/en-us/library/windows/desktop/mt637065%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396) adds high performance runtime security checks. 352 | 353 | ### Checked STL Implementations 354 | 355 | * `_GLIBCXX_DEBUG` with GCC's implementation libstdc++ implementation. See [Krister's blog article](https://kristerw.blogspot.se/2018/03/detecting-incorrect-c-stl-usage.html). 356 | 357 | ## Ignoring Warnings 358 | 359 | If it is determined by team consensus that the compiler or analyzer is warning on something that is either incorrect or unavoidable, the team will disable the specific error to as localized part of the code as possible. 360 | 361 | Be sure to reenable the warning after disabling it for a section of code. You do not want your disabled warnings to [leak into other code](http://www.forwardscattering.org/post/48). 362 | 363 | ## Testing 364 | 365 | CMake, mentioned above, has a built-in framework for executing tests. Make sure whatever build system you use has a way to execute tests built in. 366 | 367 | To further aid in executing tests, consider a library such as [Google Test](https://github.com/google/googletest), [Catch](https://github.com/philsquared/Catch), [CppUTest](https://github.com/cpputest/cpputest) or [Boost.Test](http://www.boost.org/doc/libs/release/libs/test/) to help you organize the tests. 368 | 369 | ### Unit Tests 370 | 371 | Unit tests are for small chunks of code, individual functions which can be tested standalone. 372 | 373 | ### Integration Tests 374 | 375 | There should be a test enabled for every feature or bug fix that is committed. See also [Code Coverage Analysis](#code-coverage-analysis). These are tests that are higher level than unit tests. They should still be limited in scope to individual features. 376 | 377 | ### Negative Testing 378 | 379 | Don't forget to make sure that your error handling is being tested and works properly as well. This will become obvious if you aim for 100% code coverage. 380 | 381 | ## Debugging 382 | 383 | ### GDB 384 | 385 | [GDB](https://www.gnu.org/software/gdb/) - The GNU debugger, powerful and widely used. Most IDEs implement an interface to use it. 386 | 387 | ### rr 388 | 389 | [rr](http://rr-project.org/) is a free (open source) reverse debugger that supports C++. 390 | 391 | 392 | ## Documentation Tools 393 | 394 | * [hdoc](https://hdoc.io/) the modern documentation tool for C++ 395 | 396 | 397 | ## Other Tools 398 | 399 | ### Lizard 400 | 401 | [Lizard](http://www.lizard.ws/) provides a very simple interface for running complexity analysis against a C++ codebase. 402 | 403 | ### Metrix++ 404 | 405 | [Metrix++](http://metrixplusplus.sourceforge.net/) can identify and report on the most complex sections of your code. Reducing complex code helps you and the compiler understand it better and optimize it better. 406 | 407 | ### ABI Compliance Checker 408 | 409 | [ABI Compliance Checker](http://ispras.linuxbase.org/index.php/ABI_compliance_checker) (ACC) can analyze two library versions and generates a detailed compatibility report regarding API and C++ ABI changes. This can help a library developer spot unintentional breaking changes to ensure backward compatibility. 410 | 411 | ### CNCC 412 | 413 | [Customizable Naming Convention Checker](https://github.com/mapbox/cncc) can report on identifiers in your code that do not follow certain naming conventions. 414 | 415 | ### ClangFormat 416 | 417 | [ClangFormat](http://clang.llvm.org/docs/ClangFormat.html) can check and correct code formatting to match organizational conventions automatically. [Multipart series](https://engineering.mongodb.com/post/succeeding-with-clangformat-part-1-pitfalls-and-planning/) on utilizing clang-format. 418 | 419 | ### SourceMeter 420 | 421 | [SourceMeter](https://www.sourcemeter.com/) offers a free version which provides many different metrics for your code and can also call into cppcheck. 422 | 423 | ### Bloaty McBloatface 424 | 425 | [Bloaty McBloatface](https://github.com/google/bloaty) is a binary size analyzer/profiler for unix-like platforms 426 | 427 | ### pahole 428 | 429 | [pahole](https://linux.die.net/man/1/pahole) generates data on holes in the packing of data structures and classes in compiled code. It can also the size of structures and how they fit within the system's cache lines. 430 | 431 | ### BinSkim 432 | 433 | [BinSkim](https://github.com/Microsoft/binskim) is a binary static analysis tool that provides security and correctness results for Windows Portable Executable and *nix ELF binary formats 434 | -------------------------------------------------------------------------------- /03-Style.md: -------------------------------------------------------------------------------- 1 | # Style 2 | 3 | Consistency is the most important aspect of style. The second most important aspect is following a style that the average C++ programmer is used to reading. 4 | 5 | C++ allows for arbitrary-length identifier names, so there's no reason to be terse when naming things. Use descriptive names, and be consistent in the style. 6 | 7 | * `CamelCase` 8 | * `snake_case` 9 | 10 | are common examples. *snake_case* has the advantage that it can also work with spell checkers, if desired. 11 | 12 | ## Establishing A Style Guideline 13 | 14 | Whatever style guidelines you establish, be sure to implement a `.clang-format` file that specifies the style you expect. While this cannot help with naming, it is particularly important for an open source project to maintain a consistent style. 15 | 16 | Every IDE and many editors have support for clang-format built in or easily installable with an add-in. 17 | 18 | * VSCode: [Microsoft C/C++ extension for VS Code](https://github.com/Microsoft/vscode-cpptools) 19 | * CLion: https://www.jetbrains.com/help/clion/clangformat-as-alternative-formatter.html 20 | * VisualStudio https://marketplace.visualstudio.com/items?itemName=LLVMExtensions.ClangFormat#review-details 21 | * Resharper++: https://www.jetbrains.com/help/resharper/2017.2/Using_Clang_Format.html 22 | * Vim 23 | * https://github.com/rhysd/vim-clang-format 24 | * https://github.com/chiel92/vim-autoformat 25 | * XCode: https://github.com/travisjeffery/ClangFormat-Xcode 26 | 27 | 28 | 29 | ## Common C++ Naming Conventions 30 | 31 | * Types start with upper case: `MyClass`. 32 | * Functions and variables start with lower case: `myMethod`. 33 | * Constants are all upper case: `const double PI=3.14159265358979323;`. 34 | 35 | C++ Standard Library (and other well-known C++ libraries like [Boost](http://www.boost.org/)) use these guidelines: 36 | 37 | * Macro names use upper case with underscores: `INT_MAX`. 38 | * Template parameter names use Pascal case: `InputIterator`. 39 | * All other names use snake case: `unordered_map`. 40 | 41 | ## Distinguish Private Object Data 42 | 43 | Name private data with a `m_` prefix to distinguish it from public data. `m_` stands for "member" data. 44 | 45 | ## Distinguish Function Parameters 46 | 47 | The most important thing is consistency within your codebase; this is one possibility to help with consistency. 48 | 49 | Name function parameters with an `t_` prefix. `t_` can be thought of as "the", but the meaning is arbitrary. The point is to distinguish function parameters from other variables in scope while giving us a consistent naming strategy. 50 | 51 | Any prefix or postfix can be chosen for your organization. This is just one example. *This suggestion is controversial, for a discussion about it see issue [#11](https://github.com/lefticus/cppbestpractices/issues/11).* 52 | 53 | ```cpp 54 | struct Size 55 | { 56 | int width; 57 | int height; 58 | 59 | Size(int t_width, int t_height) : width(t_width), height(t_height) {} 60 | }; 61 | 62 | // This version might make sense for thread safety or something, 63 | // but more to the point, sometimes we need to hide data, sometimes we don't. 64 | class PrivateSize 65 | { 66 | public: 67 | int width() const { return m_width; } 68 | int height() const { return m_height; } 69 | PrivateSize(int t_width, int t_height) : m_width(t_width), m_height(t_height) {} 70 | 71 | private: 72 | int m_width; 73 | int m_height; 74 | }; 75 | ``` 76 | 77 | 78 | 79 | 80 | ## Don't Name Anything Starting With `_` 81 | 82 | If you do, you risk colliding with names reserved for compiler and standard library implementation use: 83 | 84 | http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier 85 | 86 | 87 | ## Well-Formed Example 88 | 89 | ```cpp 90 | class MyClass 91 | { 92 | public: 93 | MyClass(int t_data) 94 | : m_data(t_data) 95 | { 96 | } 97 | 98 | int getData() const 99 | { 100 | return m_data; 101 | } 102 | 103 | private: 104 | int m_data; 105 | }; 106 | ``` 107 | 108 | 109 | 110 | ## Enable Out-of-Source-Directory Builds 111 | 112 | Make sure generated files go into an output folder that is separate from the source folder. 113 | 114 | 115 | ## Use `nullptr` 116 | 117 | C++11 introduces `nullptr` which is a special value denoting a null pointer. This should be used instead of `0` or `NULL` to indicate a null pointer. 118 | 119 | ## Comments 120 | 121 | Comment blocks should use `//`, not `/* */`. Using `//` makes it much easier to comment out a block of code while debugging. 122 | 123 | ```cpp 124 | // this function does something 125 | int myFunc() 126 | { 127 | } 128 | ``` 129 | 130 | To comment out this function block during debugging we might do: 131 | 132 | ```cpp 133 | /* 134 | // this function does something 135 | int myFunc() 136 | { 137 | } 138 | */ 139 | ``` 140 | 141 | which would be impossible if the function comment header used `/* */`. 142 | 143 | ## Never Use `using namespace` in a Header File 144 | 145 | This causes the namespace you are `using` to be pulled into the namespace of all files that include the header file. 146 | It pollutes the namespace and it may lead to name collisions in the future. 147 | Writing `using namespace` in an implementation file is fine though. 148 | 149 | 150 | ## Include Guards 151 | 152 | Header files must contain a distinctly-named include guard to avoid problems with including the same header multiple times and to prevent conflicts with headers from other projects. 153 | 154 | ```cpp 155 | #ifndef MYPROJECT_MYCLASS_HPP 156 | #define MYPROJECT_MYCLASS_HPP 157 | 158 | namespace MyProject { 159 | class MyClass { 160 | }; 161 | } 162 | 163 | #endif 164 | ``` 165 | 166 | You may also consider using the `#pragma once` directive instead which is quasi-standard across many compilers. 167 | It's short and makes the intent clear. 168 | 169 | 170 | ## {} Are Required for Blocks. 171 | Leaving them off can lead to semantic errors in the code. 172 | 173 | ```cpp 174 | // Bad Idea 175 | // This compiles and does what you want, but can lead to confusing 176 | // errors if modification are made in the future and close attention 177 | // is not paid. 178 | for (int i = 0; i < 15; ++i) 179 | std::cout << i << std::endl; 180 | 181 | // Bad Idea 182 | // The cout is not part of the loop in this case even though it appears to be. 183 | int sum = 0; 184 | for (int i = 0; i < 15; ++i) 185 | ++sum; 186 | std::cout << i << std::endl; 187 | 188 | 189 | // Good Idea 190 | // It's clear which statements are part of the loop (or if block, or whatever). 191 | int sum = 0; 192 | for (int i = 0; i < 15; ++i) { 193 | ++sum; 194 | std::cout << i << std::endl; 195 | } 196 | ``` 197 | 198 | ## Keep Lines a Reasonable Length 199 | 200 | ```cpp 201 | // Bad Idea 202 | // hard to follow 203 | if (x && y && myFunctionThatReturnsBool() && caseNumber3 && (15 > 12 || 2 < 3)) { 204 | } 205 | 206 | // Good Idea 207 | // Logical grouping, easier to read 208 | if (x && y && myFunctionThatReturnsBool() 209 | && caseNumber3 210 | && (15 > 12 || 2 < 3)) { 211 | } 212 | ``` 213 | 214 | Many projects and coding standards have a soft guideline that one should try to use less than about 80 or 100 characters per line. 215 | Such code is generally easier to read. 216 | It also makes it possible to have two separate files next to each other on one screen without having a tiny font. 217 | 218 | 219 | ## Use "" for Including Local Files 220 | ... `<>` is [reserved for system includes](http://blog2.emptycrate.com/content/when-use-include-verses-include). 221 | 222 | ```cpp 223 | // Bad Idea. Requires extra -I directives to the compiler 224 | // and goes against standards. 225 | #include 226 | #include 227 | 228 | // Worse Idea 229 | // Requires potentially even more specific -I directives and 230 | // makes code more difficult to package and distribute. 231 | #include 232 | #include 233 | 234 | 235 | // Good Idea 236 | // Requires no extra params and notifies the user that the file 237 | // is a local file. 238 | #include 239 | #include "MyHeader.hpp" 240 | ``` 241 | 242 | ## Initialize Member Variables 243 | ...with the member initializer list. 244 | 245 | For POD types, the performance of an initializer list is the same as manual initialization, but for other types there is a clear performance gain, see below. 246 | 247 | ```cpp 248 | // Bad Idea 249 | class MyClass 250 | { 251 | public: 252 | MyClass(int t_value) 253 | { 254 | m_value = t_value; 255 | } 256 | 257 | private: 258 | int m_value; 259 | }; 260 | 261 | // Bad Idea 262 | // This leads to an additional constructor call for m_myOtherClass 263 | // before the assignment. 264 | class MyClass 265 | { 266 | public: 267 | MyClass(MyOtherClass t_myOtherClass) 268 | { 269 | m_myOtherClass = t_myOtherClass; 270 | } 271 | 272 | private: 273 | MyOtherClass m_myOtherClass; 274 | }; 275 | 276 | // Good Idea 277 | // There is no performance gain here but the code is cleaner. 278 | class MyClass 279 | { 280 | public: 281 | MyClass(int t_value) 282 | : m_value(t_value) 283 | { 284 | } 285 | 286 | private: 287 | int m_value; 288 | }; 289 | 290 | // Good Idea 291 | // The default constructor for m_myOtherClass is never called here, so 292 | // there is a performance gain if MyOtherClass is not is_trivially_default_constructible. 293 | class MyClass 294 | { 295 | public: 296 | MyClass(MyOtherClass t_myOtherClass) 297 | : m_myOtherClass(t_myOtherClass) 298 | { 299 | } 300 | 301 | private: 302 | MyOtherClass m_myOtherClass; 303 | }; 304 | ``` 305 | 306 | In C++11 you can assign default values to each member (using `=` or using `{}`). 307 | 308 | ### Assigning default values with = 309 | 310 | ```cpp 311 | // ... // 312 | private: 313 | int m_value = 0; // allowed 314 | unsigned m_value_2 = -1; // narrowing from signed to unsigned allowed 315 | // ... // 316 | ``` 317 | This ensures that no constructor ever "forgets" to initialize a member object. 318 | 319 | ### Assigning default values with brace initialization 320 | 321 | Using brace initialization does not allow narrowing at compile-time. 322 | 323 | ```cpp 324 | // Best Idea 325 | 326 | // ... // 327 | private: 328 | int m_value{ 0 }; // allowed 329 | unsigned m_value_2 { -1 }; // narrowing from signed to unsigned not allowed, leads to a compile time error 330 | // ... // 331 | ``` 332 | 333 | Prefer `{}` initialization over `=` unless you have a strong reason not to. 334 | 335 | Forgetting to initialize a member is a source of undefined behavior bugs which are often extremely hard to find. 336 | 337 | If the member variable is not expected to change after the initialization, then mark it `const`. 338 | 339 | ```cpp 340 | class MyClass 341 | { 342 | public: 343 | MyClass(int t_value) 344 | : m_value{t_value} 345 | { 346 | } 347 | 348 | private: 349 | const int m_value{0}; 350 | }; 351 | ``` 352 | 353 | Since a const member variable cannot be assigned a new value, such a class may not have a meaningful copy assignment operator. 354 | 355 | ## Always Use Namespaces 356 | 357 | There is almost never a reason to declare an identifier in the global namespace. Instead, functions and classes should exist in an appropriately named namespace or in a class inside of a namespace. Identifiers which are placed in the global namespace risk conflicting with identifiers from other libraries (mostly C, which doesn't have namespaces). 358 | 359 | 360 | ## Use the Correct Integer Type for Standard Library Features 361 | 362 | The standard library generally uses `std::size_t` for anything related to size. The size of `size_t` is implementation defined. 363 | 364 | In general, using `auto` will avoid most of these issues, but not all. 365 | 366 | Make sure you stick with the correct integer types and remain consistent with the C++ standard library. It might not warn on the platform you are currently using, but it probably will when you change platforms. 367 | 368 | *Note that you can cause integer underflow when performing some operations on unsigned values. For example:* 369 | 370 | ```cpp 371 | std::vector v1{2,3,4,5,6,7,8,9}; 372 | std::vector v2{9,8,7,6,5,4,3,2,1}; 373 | const auto s1 = v1.size(); 374 | const auto s2 = v2.size(); 375 | const auto diff = s1 - s2; // diff underflows to a very large number 376 | ``` 377 | 378 | ## Use .hpp and .cpp for Your File Extensions 379 | 380 | Ultimately this is a matter of preference, but .hpp and .cpp are widely recognized by various editors and tools. So the choice is pragmatic. Specifically, Visual Studio only automatically recognizes .cpp and .cxx for C++ files, and Vim doesn't necessarily recognize .cc as a C++ file. 381 | 382 | One particularly large project ([OpenStudio](https://github.com/NREL/OpenStudio)) uses .hpp and .cpp for user-generated files and .hxx and .cxx for tool-generated files. Both are well recognized and having the distinction is helpful. 383 | 384 | ## Never Mix Tabs and Spaces 385 | 386 | Some editors like to indent with a mixture of tabs and spaces by default. This makes the code unreadable to anyone not using the exact same tab indentation settings. Configure your editor so this does not happen. 387 | 388 | ## Never Put Code with Side Effects Inside an assert() 389 | 390 | ```cpp 391 | assert(registerSomeThing()); // make sure that registerSomeThing() returns true 392 | ``` 393 | 394 | The above code succeeds when making a debug build, but gets removed by the compiler when making a release build, giving you different behavior between debug and release builds. 395 | This is because `assert()` is a macro which expands to nothing in release mode. 396 | 397 | ## Don't Be Afraid of Templates 398 | 399 | They can help you stick to [DRY principles](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself). 400 | They should be preferred to macros, because macros do not honor namespaces, etc. 401 | 402 | ## Use Operator Overloads Judiciously 403 | 404 | Operator overloading was invented to enable expressive syntax. Expressive in the sense that adding two big integers looks like `a + b` and not `a.add(b)`. Another common example is `std::string`, where it is very common to concatenate two strings with `string1 + string2`. 405 | 406 | However, you can easily create unreadable expressions using too much or wrong operator overloading. When overloading operators, there are three basic rules to follow as described [on stackoverflow](http://stackoverflow.com/questions/4421706/operator-overloading/4421708#4421708). 407 | 408 | Specifically, you should keep these things in mind: 409 | 410 | * Overloading `operator=()` when handling resources is a must. See [Consider the Rule of Zero](03-Style.md#consider-the-rule-of-zero) below. 411 | * For all other operators, only overload them when they are used in a context that is commonly connected to these operators. Typical scenarios are concatenating things with +, negating expressions that can be considered "true" or "false", etc. 412 | * Always be aware of the [operator precedence](http://en.cppreference.com/w/cpp/language/operator_precedence) and try to circumvent unintuitive constructs. 413 | * Do not overload exotic operators such as ~ or % unless implementing a numeric type or following a well recognized syntax in specific domain. 414 | * [Never](http://stackoverflow.com/questions/5602112/when-to-overload-the-comma-operator?answertab=votes#tab-top) overload `operator,()` (the comma operator). 415 | * Use non-member functions `operator>>()` and `operator<<()` when dealing with streams. For example, you can overload `operator<<(std::ostream &, MyClass const &)` to enable "writing" your class into a stream, such as `std::cout` or an `std::fstream` or `std::stringstream`. The latter is often used to create a string representation of a value. 416 | * There are more common operators to overload [described here](http://stackoverflow.com/questions/4421706/operator-overloading?answertab=votes#tab-top). 417 | 418 | More tips regarding the implementation details of your custom operators can be found [here](http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html). 419 | 420 | ## Avoid Implicit Conversions 421 | 422 | ### Single Parameter Constructors 423 | 424 | Single parameter constructors can be applied at compile time to automatically convert between types. This is handy for things like `std::string(const char *)` but should be avoided in general because they can add to accidental runtime overhead. 425 | 426 | Instead mark single parameter constructors as `explicit`, which requires them to be explicitly called. 427 | 428 | ### Conversion Operators 429 | 430 | Similarly to single parameter constructors, conversion operators can be called by the compiler and introduce unexpected overhead. They should also be marked as `explicit`. 431 | 432 | ```cpp 433 | //bad idea 434 | struct S { 435 | operator int() { 436 | return 2; 437 | } 438 | }; 439 | ``` 440 | 441 | ```cpp 442 | //good idea 443 | struct S { 444 | explicit operator int() { 445 | return 2; 446 | } 447 | }; 448 | ``` 449 | 450 | ## Consider the Rule of Zero 451 | 452 | The Rule of Zero states that you do not provide any of the functions that the compiler can provide (copy constructor, copy assignment operator, move constructor, move assignment operator, destructor) unless the class you are constructing does some novel form of ownership. 453 | 454 | The goal is to let the compiler provide optimal versions that are automatically maintained when more member variables are added. 455 | 456 | [This article](http://www.nirfriedman.com/2015/06/27/cpp-rule-of-zero/) provides a background and explains techniques for implementing nearly 100% of the time. 457 | -------------------------------------------------------------------------------- /04-Considering_Safety.md: -------------------------------------------------------------------------------- 1 | # Considering Safety 2 | 3 | 4 | ## Const as Much as Possible 5 | `const` tells the compiler that a variable or method is immutable. This helps the compiler optimize the code and helps the developer know if a function has a side effect. Also, using `const &` prevents the compiler from copying data unnecessarily. The [comments on `const` from John Carmack](https://web.archive.org/web/20131211065348/https://kotaku.com/454293019) are also a good read. 6 | 7 | ```cpp 8 | // Bad Idea 9 | class MyClass 10 | { 11 | public: 12 | void do_something(int i); 13 | void do_something(std::string str); 14 | }; 15 | 16 | 17 | // Good Idea 18 | class MyClass 19 | { 20 | public: 21 | void do_something(const int i); 22 | void do_something(const std::string &str); 23 | }; 24 | 25 | ``` 26 | 27 | ### Carefully Consider Your Return Types 28 | 29 | * Getters 30 | * Returning by `&` or `const &` can have significant performance savings when the normal use of the returned value is for observation 31 | * Returning by value is better for thread safety and if the normal use of the returned value is to make a copy anyhow, there's no performance lost 32 | * If your API uses covariant return types, you must return by `&` or `*` 33 | * Temporaries and local values 34 | * Always return by value. 35 | 36 | 37 | references: https://github.com/lefticus/cppbestpractices/issues/21 https://twitter.com/lefticus/status/635943577328095232 38 | 39 | ### Do not pass and return simple types by const ref 40 | 41 | ```cpp 42 | // Very Bad Idea 43 | class MyClass 44 | { 45 | public: 46 | explicit MyClass(const int& t_int_value) 47 | : m_int_value(t_int_value) 48 | { 49 | } 50 | 51 | const int& get_int_value() const 52 | { 53 | return m_int_value; 54 | } 55 | 56 | private: 57 | int m_int_value; 58 | } 59 | ``` 60 | 61 | Instead, pass and return simple types by value. If you plan not to change passed value, declare them as `const`, but not `const` refs: 62 | 63 | ```cpp 64 | // Good Idea 65 | class MyClass 66 | { 67 | public: 68 | explicit MyClass(const int t_int_value) 69 | : m_int_value(t_int_value) 70 | { 71 | } 72 | 73 | int get_int_value() const 74 | { 75 | return m_int_value; 76 | } 77 | 78 | private: 79 | int m_int_value; 80 | } 81 | ``` 82 | 83 | Why? Because passing and returning by reference leads to pointer operations, instead of much faster passing of values in processor registers. 84 | 85 | ## Avoid Raw Memory Access 86 | 87 | Raw memory access, allocation and deallocation, are difficult to get correct in C++ without [risking memory errors and leaks](http://blog2.emptycrate.com/content/nobody-understands-c-part-6-are-you-still-using-pointers). C++11 provides tools to avoid these problems. 88 | 89 | ```cpp 90 | // Bad Idea 91 | MyClass *myobj = new MyClass; 92 | 93 | // ... 94 | delete myobj; 95 | 96 | 97 | // Good Idea 98 | auto myobj = std::make_unique(constructor_param1, constructor_param2); // C++14 99 | auto myobj = std::unique_ptr(new MyClass(constructor_param1, constructor_param2)); // C++11 100 | auto mybuffer = std::make_unique(length); // C++14 101 | auto mybuffer = std::unique_ptr(new char[length]); // C++11 102 | 103 | // or for reference counted objects 104 | auto myobj = std::make_shared(); 105 | 106 | // ... 107 | // myobj is automatically freed for you whenever it is no longer used. 108 | ``` 109 | 110 | ## Use `std::array` or `std::vector` Instead of C-style Arrays 111 | 112 | Both of these guarantee contiguous memory layout of objects and can (and should) completely replace your usage of C-style arrays for many of the reasons listed for not using bare pointers. 113 | 114 | Also, [avoid](http://stackoverflow.com/questions/3266443/can-you-use-a-shared-ptr-for-raii-of-c-style-arrays) using `std::shared_ptr` to hold an array. 115 | 116 | ## Use Exceptions 117 | 118 | Exceptions cannot be ignored. Return values, such as using `boost::optional`, can be ignored and if not checked can cause crashes or memory errors. An exception, on the other hand, can be caught and handled. Potentially all the way up the highest level of the application with a log and automatic restart of the application. 119 | 120 | Stroustrup, the original designer of C++, [makes this point](http://www.stroustrup.com/bs_faq2.html#exceptions-why) much better than I ever could. 121 | 122 | ## Use C++-style cast instead of C-style cast 123 | Use the C++-style cast (static\_cast<>, dynamic\_cast<> ...) instead of the C-style cast. The C++-style cast allows more compiler checks and is considerably safer. 124 | 125 | ```cpp 126 | // Bad Idea 127 | double x = getX(); 128 | int i = (int) x; 129 | 130 | // Not a Bad Idea 131 | int i = static_cast(x); 132 | ``` 133 | Additionally the C++ cast style is more visible and has the possibility to search for. 134 | 135 | But consider refactoring of program logic (for example, additional checking on overflow and underflow) if you need to cast `double` to `int`. Measure three times and cut 0.9999999999981 times. 136 | 137 | ## Do not define a variadic function 138 | Variadic functions can accept a variable number of parameters. The probably best known example is printf(). You have the possibility to define this kind of functions by yourself but this is a possible security risk. The usage of variadic functions is not type safe and the wrong input parameters can cause a program termination with an undefined behavior. This undefined behavior can be exploited to a security problem. 139 | If you have the possibility to use a compiler that supports C++11, you can use variadic templates instead. 140 | 141 | [It is technically possible to make typesafe C-style variadic functions with some compilers](https://github.com/lefticus/cppbestpractices/issues/53) 142 | 143 | ## Additional Resources 144 | 145 | [How to Prevent The Next Heartbleed](https://dwheeler.com/essays/heartbleed.html) by David Wheeler is a good analysis of the current state of code safety and how to ensure safe code. 146 | -------------------------------------------------------------------------------- /05-Considering_Maintainability.md: -------------------------------------------------------------------------------- 1 | # Considering Maintainability 2 | 3 | 4 | ## Avoid Compiler Macros 5 | 6 | Compiler definitions and macros are replaced by the preprocessor before the compiler is ever run. This can make debugging very difficult because the debugger doesn't know where the source came from. 7 | 8 | ```cpp 9 | // Bad Idea 10 | #define PI 3.14159; 11 | 12 | // Good Idea 13 | namespace my_project { 14 | class Constants { 15 | public: 16 | // if the above macro would be expanded, then the following line would be: 17 | // static const double 3.14159 = 3.14159; 18 | // which leads to a compile-time error. Sometimes such errors are hard to understand. 19 | static constexpr double PI = 3.14159; 20 | }; 21 | } 22 | ``` 23 | 24 | ## Consider Avoiding Boolean Parameters 25 | 26 | They do not provide any additional meaning while reading the code. You can either create a separate function that has a more meaningful name, or pass an enumeration that makes the meaning more clear. 27 | 28 | See http://mortoray.com/2015/06/15/get-rid-of-those-boolean-function-parameters/ for more information. 29 | 30 | ## Avoid Raw Loops 31 | 32 | Know and understand the existing C++ standard algorithms and put them to use. 33 | 34 | * See [cppreference](https://en.cppreference.com/w/cpp/algorithm) 35 | * Watch [C++ Seasoning](https://www.youtube.com/watch?v=qH6sSOr-yk8) 36 | 37 | Consider a call to `[]` as a potential code smell, indicating that an algorithm was not used where it could have been. 38 | 39 | 40 | ## Never Use `assert` With Side Effects 41 | 42 | ```cpp 43 | // Bad Idea 44 | assert(set_value(something)); 45 | 46 | // Better Idea 47 | [[maybe_unused]] const auto success = set_value(something); 48 | assert(success); 49 | ``` 50 | 51 | The `assert()` will be removed in release builds which will prevent the `set_value` call from ever happening. 52 | 53 | So while the second version is uglier, the first version is simply not correct. 54 | 55 | 56 | ## Properly Utilize 'override' and 'final' 57 | 58 | These keywords make it clear to other developers how virtual functions are being utilized, can catch potential errors if the signature of a virtual function changes, and can possibly [hint to the compiler](http://stackoverflow.com/questions/7538820/how-does-the-compiler-benefit-from-cs-new-final-keyword) of optimizations that can be performed. 59 | -------------------------------------------------------------------------------- /06-Considering_Portability.md: -------------------------------------------------------------------------------- 1 | # Considering Portability 2 | 3 | ## Know Your Types 4 | 5 | Most portability issues that generate warnings are because we are not careful about our types. Standard library and arrays are indexed with `size_t`. Standard container sizes are reported in `size_t`. If you get the handling of `size_t` wrong, you can create subtle lurking 64-bit issues that arise only after you start to overflow the indexing of 32-bit integers. char vs unsigned char. 6 | 7 | http://www.viva64.com/en/a/0010/ 8 | 9 | ## Use The Standard Library 10 | 11 | ### `std::filesystem` 12 | 13 | C++17 added a new `filesystem` library which provides portable filesystem access across all supporting compilers 14 | 15 | ### `std::thread` 16 | 17 | C++11's threading capabilities should be utilized over `pthread` or `WinThreads`. 18 | 19 | ## Other Concerns 20 | 21 | Most of the other concerns in this document ultimately come back to portability issues. [Avoid statics](07-Considering_Threadability.md#statics) is particularly of note. 22 | -------------------------------------------------------------------------------- /07-Considering_Threadability.md: -------------------------------------------------------------------------------- 1 | # Considering Threadability 2 | 3 | ## Avoid Global Data 4 | 5 | Global data leads to unintended side effects between functions and can make code difficult or impossible to parallelize. Even if the code is not intended today for parallelization, there is no reason to make it impossible for the future. 6 | 7 | ### Statics 8 | 9 | Besides being global data, statics are not always constructed and deconstructed as you would expect. This is particularly true in cross-platform environments. See for example, [this g++ bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66830) regarding the order of destruction of shared static data loaded from dynamic modules. 10 | 11 | ### Shared Pointers 12 | 13 | `std::shared_ptr` is "as good as a global" (http://stackoverflow.com/a/18803611/29975) because it allows multiple pieces of code to interact with the same data. 14 | 15 | ### Singletons 16 | 17 | A singleton is often implemented with a static and/or `shared_ptr`. 18 | 19 | ## Avoid Heap Operations 20 | 21 | Much slower in threaded environments. In many or maybe even most cases, copying data is faster. Plus with move operations and such and things. 22 | 23 | ## Mutex and mutable go together (M&M rule, C++11) 24 | For member variables it is good practice to use mutex and mutable together. This applies in both ways: 25 | * A mutable member variable is presumed to be a shared variable so it should be synchronized with a mutex (or made atomic) 26 | * If a member variable is itself a mutex, it should be mutable. This is required to use it inside a const member function. 27 | 28 | For more information see the following article from Herb Sutter: http://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/ 29 | 30 | See also [related safety discussion](04-Considering_Safety.md#consider-return-by-value-for-mutable-data-const--for-immutable) about `const &` return values 31 | -------------------------------------------------------------------------------- /08-Considering_Performance.md: -------------------------------------------------------------------------------- 1 | # Considering Performance 2 | 3 | ## Build Time 4 | 5 | 6 | 7 | ### Forward Declare When Possible 8 | 9 | This: 10 | 11 | ```cpp 12 | // some header file 13 | class MyClass; 14 | 15 | void doSomething(const MyClass &); 16 | ``` 17 | 18 | instead of: 19 | 20 | ```cpp 21 | // some header file 22 | #include "MyClass.hpp" 23 | 24 | void doSomething(const MyClass &); 25 | ``` 26 | 27 | 28 | This applies to templates as well: 29 | 30 | ```cpp 31 | template class MyTemplatedType; 32 | ``` 33 | 34 | This is a proactive approach to reduce compilation time and rebuilding dependencies. 35 | 36 | *Note: forward declaration does prevent more inlining and optimizations. It's recommended to use Link Time Optimization or Link Time Code Generation for release builds.* 37 | 38 | ### Avoid Unnecessary Template Instantiations 39 | 40 | Templates are not free to instantiate. Instantiating many templates, or templates with more code than necessary increases compiled code size and build time. 41 | 42 | For more examples see [this article](http://blog2.emptycrate.com/content/template-code-bloat-revisited-smaller-makeshared). 43 | 44 | ### Avoid Recursive Template Instantiations 45 | 46 | Recursive template instantiations can result in a significant load on the compiler and more difficult to understand code. 47 | 48 | [Consider using variadic expansions and folds when possible instead.](http://articles.emptycrate.com/2016/05/14/folds_in_cpp11_ish.html) 49 | 50 | ### Analyze the Build 51 | 52 | The tool [Templight](https://github.com/mikael-s-persson/templight) can be used to analyze the build time of your project. It takes some effort to get built, but once you do, it's a drop in replacement for clang++. 53 | 54 | After you build using Templight, you will need to analyze the results. The [templight-tools](https://github.com/mikael-s-persson/templight-tools) project provides various methods. (Author's Note: I suggest using the callgrind converter and visualizing the results with kcachegrind). 55 | 56 | 57 | 58 | ### Firewall Frequently Changing Header Files 59 | 60 | 61 | 62 | #### Don't Unnecessarily Include Headers 63 | 64 | The compiler has to do something with each include directive it sees. Even if it stops as soon as it sees the `#ifndef` include guard, it still had to open the file and begin processing it. 65 | 66 | [include-what-you-use](https://github.com/include-what-you-use/include-what-you-use) is a tool that can help you identify which headers you need. 67 | 68 | #### Reduce the load on the preprocessor 69 | 70 | This is a general form of "Firewall Frequently Changing Header Files" and "Don't Unnecessarily Include Headers." Tools like BOOST_PP can be very helpful, but they also put a huge burden on the preprocessor. 71 | 72 | ### Consider using precompiled headers 73 | 74 | The usage of precompiled headers can considerably reduce the compile time in large projects. Selected headers are compiled to an intermediate form (PCH files) that can be faster processed by the compiler. It is recommended to define only frequently used header that changes rarely as precompiled header (e.g. system and library headers) to achieve the compile time reduction. 75 | But you have to keep in mind, that using precompiled headers has several disadvantages: 76 | * The usage of precompiled header is not portable. 77 | * The generated PCH files are machine dependent. 78 | * The generated PCH files can be quite large. 79 | * It can break your header dependencies. Because of the precompiled headers, every file has the possibility to include every header that is marked as a precompiled header. In result it can happen, that the build fails if you disable the precompiled headers. This can be an issue if you ship something like a library. Because of this it is highly recommend to build once with precompiled header enabled and a second time without them. 80 | 81 | Precompiled headers is supported by the most common compiler, like [GCC](https://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html), [Clang](http://clang.llvm.org/docs/PCHInternals.html) and [Visual Studio](https://msdn.microsoft.com/en-us/library/szfdksca.aspx). 82 | Tools like [cotire](https://github.com/sakra/cotire/) (a plugin for cmake) can help you to add precompiled headers to your build system. 83 | 84 | ### Consider Using Tools 85 | 86 | These are not meant to supersede good design 87 | 88 | * [ccache](https://ccache.samba.org/), compile results caching for unix-like operating systems 89 | * [clcache](https://github.com/frerich/clcache), compile results caching for cl.exe (MSVC) 90 | * [warp](https://github.com/facebook/warp), Facebook's preprocessor 91 | 92 | ### Put tmp on Ramdisk 93 | 94 | See [this](https://www.youtube.com/watch?v=t4M3yG1dWho) YouTube video for more details. 95 | 96 | ### Use the gold linker 97 | 98 | If on Linux, consider using the gold linker for GCC. 99 | 100 | ## Runtime 101 | 102 | ### Analyze the Code! 103 | 104 | There's no real way to know where your bottlenecks are without analyzing the code. 105 | 106 | A list of code profilers: 107 | * [Intel VTune](https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/vtune-profiler.html) 108 | * [Coz - Causal Profiling](https://github.com/plasma-umass/coz) 109 | * [Sleepy](http://www.codersnotes.com/sleepy) 110 | * [Dyninst](https://dyninst.org/) 111 | * [AMD CodeXL](https://github.com/GPUOpen-Archive/CodeXL) 112 | * [lukestackwalker](http://lukestackwalker.sourceforge.net/) 113 | 114 | ### Simplify the Code 115 | 116 | The cleaner, simpler, and easier to read the code is, the better chance the compiler has at implementing it well. 117 | 118 | ### Use Initializer Lists 119 | 120 | ```cpp 121 | // This 122 | std::vector mos{mo1, mo2}; 123 | 124 | // -or- 125 | auto mos = std::vector{mo1, mo2}; 126 | ``` 127 | 128 | ```cpp 129 | // Don't do this 130 | std::vector mos; 131 | mos.push_back(mo1); 132 | mos.push_back(mo2); 133 | ``` 134 | 135 | Initializer lists are significantly more efficient; reducing object copies and resizing of containers. 136 | 137 | ### Reduce Temporary Objects 138 | 139 | ```cpp 140 | // Instead of 141 | auto mo1 = getSomeModelObject(); 142 | auto mo2 = getAnotherModelObject(); 143 | 144 | doSomething(mo1, mo2); 145 | ``` 146 | 147 | ```cpp 148 | // consider: 149 | 150 | doSomething(getSomeModelObject(), getAnotherModelObject()); 151 | ``` 152 | 153 | This sort of code prevents the compiler from performing a move operation... 154 | 155 | ### Enable move operations 156 | 157 | Move operations are one of the most touted features of C++11. They allow the compiler to avoid extra copies by moving temporary objects instead of copying them in certain cases. 158 | 159 | Certain coding choices we make (such as declaring our own destructor or assignment operator or copy constructor) prevents the compiler from generating a move constructor. 160 | 161 | For most code, a simple 162 | 163 | ```cpp 164 | ModelObject(ModelObject &&) = default; 165 | ``` 166 | 167 | would suffice. However, MSVC2013 doesn't seem to like this code yet. 168 | 169 | ### Kill `shared_ptr` Copies 170 | 171 | `shared_ptr` objects are much more expensive to copy than you'd think they would be. This is because the reference count must be atomic and thread-safe. So this comment just re-enforces the note above: avoid temporaries and too many copies of objects. Just because we are using a pImpl it does not mean our copies are free. 172 | 173 | ### Reduce Copies and Reassignments as Much as Possible 174 | 175 | For more simple cases, the ternary operator can be used: 176 | 177 | ```cpp 178 | // Bad Idea 179 | std::string somevalue; 180 | 181 | if (caseA) { 182 | somevalue = "Value A"; 183 | } else { 184 | somevalue = "Value B"; 185 | } 186 | ``` 187 | 188 | ```cpp 189 | // Better Idea 190 | const std::string somevalue = caseA ? "Value A" : "Value B"; 191 | ``` 192 | 193 | More complex cases can be facilitated with an [immediately-invoked lambda](http://blog2.emptycrate.com/content/complex-object-initialization-optimization-iife-c11). 194 | 195 | ```cpp 196 | // Bad Idea 197 | std::string somevalue; 198 | 199 | if (caseA) { 200 | somevalue = "Value A"; 201 | } else if(caseB) { 202 | somevalue = "Value B"; 203 | } else { 204 | somevalue = "Value C"; 205 | } 206 | ``` 207 | 208 | ```cpp 209 | // Better Idea 210 | const std::string somevalue = [&](){ 211 | if (caseA) { 212 | return "Value A"; 213 | } else if (caseB) { 214 | return "Value B"; 215 | } else { 216 | return "Value C"; 217 | } 218 | }(); 219 | ``` 220 | 221 | 222 | ### Avoid Excess Exceptions 223 | 224 | Exceptions which are thrown and captured internally during normal processing slow down the application execution. They also destroy the user experience from within a debugger, as debuggers monitor and report on each exception event. It is best to just avoid internal exception processing when possible. 225 | 226 | ### Get rid of “new” 227 | 228 | We already know that we should not be using raw memory access, so we are using `unique_ptr` and `shared_ptr` instead, right? 229 | Heap allocations are much more expensive than stack allocations, but sometimes we have to use them. To make matters worse, creating a `shared_ptr` actually requires 2 heap allocations. 230 | 231 | However, the `make_shared` function reduces this down to just one. 232 | 233 | ```cpp 234 | std::shared_ptr(new ModelObject_Impl()); 235 | 236 | // should become 237 | std::make_shared(); // (it's also more readable and concise) 238 | ``` 239 | 240 | ### Prefer `unique_ptr` to `shared_ptr` 241 | 242 | If possible use `unique_ptr` instead of `shared_ptr`. The `unique_ptr` does not need to keep track of its copies because it is not copyable. Because of this it is more efficient than the `shared_ptr`. Equivalent to `shared_ptr` and `make_shared` you should use `make_unique` (C++14 or greater) to create the `unique_ptr`: 243 | 244 | ```cpp 245 | std::make_unique(); 246 | ``` 247 | 248 | Current best practices suggest returning a `unique_ptr` from factory functions as well, then converting the `unique_ptr` to a `shared_ptr` if necessary. 249 | 250 | ```cpp 251 | std::unique_ptr factory(); 252 | 253 | auto shared = std::shared_ptr(factory()); 254 | ``` 255 | 256 | ### Get rid of std::endl 257 | 258 | `std::endl` implies a flush operation. It's equivalent to `"\n" << std::flush`. 259 | 260 | 261 | ### Limit Variable Scope 262 | 263 | Variables should be declared as late as possible, and ideally only when it's possible to initialize the object. Reduced variable scope results in less memory being used, more efficient code in general, and helps the compiler optimize the code further. 264 | 265 | ```cpp 266 | // Good Idea 267 | for (int i = 0; i < 15; ++i) 268 | { 269 | MyObject obj(i); 270 | // do something with obj 271 | } 272 | 273 | // Bad Idea 274 | MyObject obj; // meaningless object initialization 275 | for (int i = 0; i < 15; ++i) 276 | { 277 | obj = MyObject(i); // unnecessary assignment operation 278 | // do something with obj 279 | } 280 | // obj is still taking up memory for no reason 281 | ``` 282 | 283 | For C++17 and onwards, consider using init-statement in the `if` and `switch` statements: 284 | 285 | ```cpp 286 | if (MyObject obj(index); obj.good()) { 287 | // do something if obj is good 288 | } else { 289 | // do something if obj is not good 290 | } 291 | ``` 292 | 293 | [This topic has an associated discussion thread](https://github.com/lefticus/cppbestpractices/issues/52). 294 | 295 | ### Prefer `double` to `float`, But Test First 296 | 297 | Depending on the situation and the compiler's ability to optimize, one may be faster over the other. Choosing `float` will result in lower precision and may be slower due to conversions. On vectorizable operations `float` may be faster if you are able to sacrifice precision. 298 | 299 | `double` is the recommended default choice as it is the default type for floating point values in C++. 300 | 301 | See this [stackoverflow](http://stackoverflow.com/questions/4584637/double-or-float-which-is-faster) discussion for some more information. 302 | 303 | ### Prefer `++i` to `i++` 304 | ... when it is semantically correct. Pre-increment is [faster](http://blog2.emptycrate.com/content/why-i-faster-i-c) than post-increment because it does not require a copy of the object to be made. 305 | 306 | ```cpp 307 | // Bad Idea 308 | for (int i = 0; i < 15; i++) 309 | { 310 | std::cout << i << '\n'; 311 | } 312 | 313 | // Good Idea 314 | for (int i = 0; i < 15; ++i) 315 | { 316 | std::cout << i << '\n'; 317 | } 318 | ``` 319 | 320 | Even if many modern compilers will optimize these two loops to the same assembly code, it is still good practice to prefer `++i`. There is absolutely no reason not to and you can never be certain that your code will not pass a compiler that does not optimize this. 321 | You should be also aware that the compiler will not be able optimize this only for integer types and not necessarily for all iterator or other user defined types. 322 | The bottom line is that it is always easier and recommended to use the pre-increment operator if it is semantically identical to the post-increment operator. 323 | 324 | ### Char is a char, string is a string 325 | 326 | ```cpp 327 | // Bad Idea 328 | std::cout << someThing() << "\n"; 329 | 330 | // Good Idea 331 | std::cout << someThing() << '\n'; 332 | ``` 333 | 334 | This is very minor, but a `"\n"` has to be parsed by the compiler as a `const char *` which has to do a range check for `\0` when writing it to the stream (or appending to a string). A '\n' is known to be a single character and avoids many CPU instructions. 335 | 336 | If used inefficiently very many times it might have an impact on your performance, but more importantly thinking about these two usage cases gets you thinking more about what the compiler and runtime has to do to execute your code. 337 | 338 | 339 | ### Never Use `std::bind` 340 | 341 | `std::bind` is almost always way more overhead (both compile time and runtime) than you need. Instead simply use a lambda. 342 | 343 | ```cpp 344 | // Bad Idea 345 | auto f = std::bind(&my_function, "hello", std::placeholders::_1); 346 | f("world"); 347 | 348 | // Good Idea 349 | auto f = [](const std::string &s) { return my_function("hello", s); }; 350 | f("world"); 351 | ``` 352 | 353 | 354 | ### Know The Standard Library 355 | 356 | Properly use the already highly optimized components of the vendor provided standard library. 357 | 358 | #### `in_place_t` And Related 359 | 360 | Be aware of how to use `in_place_t` and related tags for efficient creation of objects such as `std::tuple`, `std::any` and `std::variant`. 361 | -------------------------------------------------------------------------------- /09-Considering_Correctness.md: -------------------------------------------------------------------------------- 1 | # Considering Correctness 2 | 3 | ## Avoid Typeless Interfaces 4 | 5 | 6 | Bad Idea: 7 | 8 | ```cpp 9 | std::string find_file(const std::string &base, const std::string &pattern); 10 | ``` 11 | 12 | Better Idea: 13 | 14 | ```cpp 15 | std::filesystem::path find_file(const std::filesystem::path &base, const std::regex &pattern); 16 | ``` 17 | 18 | The above is better but still suffers from having implicit conversions from `std::string` to `std::filesystem::path` and back. 19 | 20 | Consider using a typesafe library like 21 | 22 | * https://foonathan.net/type_safe/ 23 | * https://github.com/rollbear/strong_type 24 | * https://github.com/joboccara/NamedType 25 | 26 | Note that stronger typing can also allow for more compiler optimizations. 27 | 28 | * [Sorting in C vs C++](Sorting%20in%20C%20vs%20C++.pdf) 29 | -------------------------------------------------------------------------------- /10-Enable_Scripting.md: -------------------------------------------------------------------------------- 1 | # Enable Scripting 2 | 3 | The combination of scripting and compiled languages is very powerful. It gives us the things we've come to love about compiled languages: type safety, performance, thread safety options, consistent memory model while also giving us the flexibility to try something new quickly without a full rebuild. 4 | 5 | The VM based compiled languages have learned this already: JRuby, Jython, IronRuby, IronPython 6 | 7 | * [ChaiScript](http://chaiscript.com/) 8 | * [AngelScript](http://www.angelcode.com/angelscript/) 9 | * [luabind](http://www.rasterbar.com/products/luabind.html) 10 | * [sol2](https://github.com/ThePhD/sol2) (bindings for Lua) 11 | * [SWIG](http://www.swig.org/) (simplified wrapper and interface generator) 12 | * [pybind11](https://pybind11.readthedocs.io/en/stable/) (Python and modern C++ interoperability) 13 | -------------------------------------------------------------------------------- /11-Further_Reading.md: -------------------------------------------------------------------------------- 1 | # Further Reading 2 | 3 | *Note: This book has now inspired a video series from O'Reilly, [Learning C++ Best Practices](http://shop.oreilly.com/product/0636920049814.do)* 4 | 5 | ## C++ 6 | 7 | * https://github.com/isocpp/CppCoreGuidelines The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and best practices about coding in C++ 8 | * https://www.gitbook.com/book/alexastva/the-ultimate-question-of-programming-refactoring-/details - The Ultimate Question of Programming, Refactoring, and Everything 9 | * http://llvm.org/docs/CodingStandards.html - LLVM Coding Standards - very well written 10 | * http://geosoft.no/development/cppstyle.html 11 | * https://google.github.io/styleguide/cppguide.html (Note that Google's standard document makes several recommendations which we will NOT be following. For example, they explicitly forbid the use of exceptions, which makes [RAII](http://blog2.emptycrate.com/content/nobody-understands-c-part-2-raii) impossible.) 12 | * https://isocpp.org/faq/ 13 | * http://www.cplusplus.com/ 14 | * http://www.gamasutra.com/view/news/128836/InDepth_Static_Code_Analysis.php - Article from John Carmack on the advantages of static analysis 15 | * https://svn.boost.org/trac/boost/wiki/BestPracticeHandbook - Best Practice Handbook from Nial Douglas 16 | * http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=ListOfChecks 17 | * http://emptycrate.com/ 18 | * http://stackoverflow.com/questions/tagged/c%2b%2b-faq?sort=votes&pageSize=15 - StackOverflow C++ FAQ 19 | * http://codergears.com/qacenter/ discussion center for C and C++ best practices 20 | * http://www.viva64.com/en/b/0391/ The Ultimate Question of Programming, Refactoring, and Everything 21 | 22 | ## CMake 23 | 24 | * https://cmake.org/cmake/help/latest/manual/cmake.1.html - Be aware that there are `--warn` command line options for CMake that can catch some issues. 25 | * https://github.com/Akagi201/learning-cmake 26 | * https://codingnest.com/basic-cmake/ 27 | * https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1 - Effective CMake online book 28 | * https://pabloariasal.github.io/2018/02/19/its-time-to-do-cmake-right/ 29 | * https://cliutils.gitlab.io/modern-cmake/ - An Introduction to Modern CMake 30 | -------------------------------------------------------------------------------- /12-Final_Thoughts.md: -------------------------------------------------------------------------------- 1 | # Final Thoughts 2 | 3 | Expand your horizons and use other programming languages. Other languages have different constructs and expressions. Learning what else is out there will encourage you to be more creative with your C++ and write cleaner, more expressive code. 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. 2 | To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/. 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cppbestpractices 2 | 3 | [![Join the chat at https://gitter.im/lefticus/cppbestpractices](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lefticus/cppbestpractices?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | 5 | Collaborative Collection of C++ Best Practices 6 | 7 | For more information please see the [Preface](01-Preface.md). 8 | 9 | This online resource is part of Jason Turner's collection of C++ Best Practices resources. 10 | 11 | * [C++ Best Practices Book](https://leanpub.com/cppbestpractices) 12 | * [C++ Weekly YouTube Channel](https://www.youtube.com/user/lefticus1) 13 | * [The Ultimate CMake/C++ Starter Project](https://github.com/lefticus/cpp_starter_project/) 14 | * [Learning C++ Best Practices - O'Reilly Video](http://shop.oreilly.com/product/0636920049814.do) 15 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * [Preface](01-Preface.md) 4 | * [Use the Tools Available](02-Use_the_Tools_Available.md) 5 | * [Style](03-Style.md) 6 | * [Considering Safety](04-Considering_Safety.md) 7 | * [Considering Maintainability](05-Considering_Maintainability.md) 8 | * [Considering Portability](06-Considering_Portability.md) 9 | * [Considering Threadability](07-Considering_Threadability.md) 10 | * [Considering Performance](08-Considering_Performance.md) 11 | * [Considering Correctness](09-Considering_Correctness.md) 12 | * [Enable Scripting](10-Enable_Scripting.md) 13 | * [Further Reading](11-Further_Reading.md) 14 | * [Final Thoughts](12-Final_Thoughts.md) 15 | -------------------------------------------------------------------------------- /Sorting in C vs C++.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cpp-best-practices/cppbestpractices/d57b14ec6d7f13f0af65f9bde62aa3ebd5fb588a/Sorting in C vs C++.pdf -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ "github" ], 3 | "pluginsConfig": { 4 | "github": { 5 | "url": "https://github.com/lefticus/cppbestpractices" 6 | } 7 | } 8 | 9 | } 10 | --------------------------------------------------------------------------------