C++ for C# Developers
Total Page:16
File Type:pdf, Size:1020Kb
JacksonDunstan.com Copyright © 2021 Jackson Dunstan All rights reserved Table of Contents 1. Introduction 2. Primitive Types and Literals 3. Variables and Initialization 4. Functions 5. Build Model 6. Control Flow 7. Pointers, Arrays, and Strings 8. References 9. Enumerations 10. Struct Basics 11. Struct Functions 12. Constructors and Destructors 13. Initialization 14. Inheritance 15. Struct and Class Permissions 16. Struct and Class Wrapup 17. Namespaces 18. Exceptions 19. Dynamic Allocation 20. Implicit Type Conversion 21. Casting and RTTI 22. Lambdas 23. Compile-Time Programming 24. Preprocessor 25. Intro to Templates 26. Template Parameters 27. Template Deduction and Specialization 28. Variadic Templates 29. Template Constraints 30. Type Aliases 31. Deconstructing and Attributes 32. Thread-Local Storage and Volatile 33. Alignment, Assembly, and Language Linkage 34. Fold Expressions and Elaborated Type Specifiers 35. Modules, The New Build Model 36. Coroutines 37. Missing Language Features 38. C Standard Library 39. Language Support Library 40. Utilities Library 41. System Integration Library 42. Numbers Library 43. Threading Library 44. Strings Library 45. Array Containers Library 46. Other Containers Library 47. Containers Library Wrapup 48. Algorithms Library 49. Ranges and Parallel Algorithms 50. I/O Library 51. Missing Library Features 52. Idioms and Best Practices 53. Conclusion 1. Introduction History C++’s predecessor is C, which debuted in 1972. It is still the most used language with C++ in fourth place and C# in fifth. C++ got started with the name “C with Classes” in 1979. The name C++ came later in 1982. The original C++ compiler, Cfront, output C source files which were then compiled to machine code. That compiler has long since been replaced and modern compilers all compile C++ directly to machine code. Major additions to the language were added with “C++ 2.0” in 1989 and the language was then standardized by ISO in 1998. Colloquially, this was called C++98 and began the convention where the year is added to name a version of the language. It also formalized the process of designing and standardizing the language via a committee and various working groups. Minor changes to the language in 2003 resulted in C++03, but the “Modern C++” era began with huge changes to the language in C++11. This also quickened the standardization process from the previous eight year gap to just three years. This meant that we got minor changes in C++14, relatively big changes in C++17, and huge changes once again in C++20. Game engines such as Unreal, Cryengine, and Lumberyard all support at least C++17, if not C++20. At this point the language has little resemblance to C. Much C code will still compile as C++, but idiomatic C++ is only superficially similar to C. Standard Library Every release of C++ includes what is called the “Standard Library.” This is often called the “STL,” meaning “Standard Template Library,” for its heavy use of a C++ language feature called templates. This library is also standardized by ISO along with the language itself. The Standard Library is similar to .NET’s Framework Class Library or CoreFX. The architectural approach is for the C++ language to have powerful, low-level language features so more can be implemented in libraries instead of directly included in the language. For example, the language doesn’t include a string class. Instead, the Standard Library provides a string class that is efficiently implemented with low-level language features. The following table shows the major sections of the Standard Library and their loose equivalents in .NET: Standard Library C++ C# Section Language numeric_limits::max int.MaxValue support Concepts default_initializable where T : new() Diagnostics exception System.Exception Utilities tuple<int, float> (int, float) Strings string System.String Containers vector List Iterators begin() GetEnumerator() Standard Library C++ C# Section Ranges views::filter Enumerable.Where Algorithms transform Enumerable.Select Numerics accumulate Enumerable.Aggregate Localization toupper Char.ToUpper I/O fstream FileStream File system copy File.Copy Regular regex Regex expressions Atomic atomic++ Interlocked.Increment operations Threading thread Thread Some game programming environments do not use the Standard Library, or at least minimize its use. EA has implemented their own version called EASTL. Unreal has many built-in similar types (FString vs. string) and functions (MakeUnique vs. make_unique). These libraries benefit from the same low-level language features that the Standard Library is built on, but instead use them to efficiently reimplement what would be language features in many other languages. Tools The main tool is, of course, the compiler. There are many good options these days, but here are some of the most popular ones: Open Compiler Cost Platforms Source Free and Microsoft Visual Studio No Windows Paid GCC (GNU Compiler Windows, Free Yes Collection) macOS, Linux Windows, Clang Free Yes macOS, Linux Windows, Intel C++ Free No macOS, Linux There are also many IDEs available with the usual combination of features: a text editor, compiler execution, interactive debugger, etc. Here are some popular options: Open IDE Cost Platforms Source Microsoft Visual Free and No Windows Studio Paid Apple Xcode Free No macOS Windows, JetBrains CLion Paid No macOS, Linux Open IDE Cost Platforms Source Microsoft Visual Windows, Free Yes Studio Code macOS, Linux Many static analyzers, known as “linters,” and dynamic analyzers are available. The Clang sanitizers suite is free, open source, and has Unreal support. Commercial tools such as Coverity SAST are also available. Clang format and many IDEs can enforce style guides and automatically reformat code. Documentation The C++ standard is available for purchase, but almost no C++ developers actually buy it. A draft version is available for free and will be nearly identical, but it is extremely long and technical so it is also only a reference of last resort. Instead of the standard itself, most developers read reference sites such as cppreference.com just as they would read Microsoft Docs (a.k.a. MSDN) for C# reference. Many guideline documents exist for C++. The C++ Core Guidelines, Google C++ style guide, and engine-specific standards are all commonly used. The C++ Core Guidelines, in particular, has a companion Guidelines Support Library (GSL) to enforce and facilitate the guidelines. Community There are many places where the community of developers congregate. Here are a few: The C++ language Slack has 16,000 members The /r/cpp subreddit has 185,000 members The /r/Cplusplus subreddit has 25,000 members CppCon is held annually and posts hundreds of talks Engine-specific forums are generally very active Many C++ GitHub repositories have 10,000+ stars and active Issues sections 2. Primitive Types and Literals Types Let’s start with integers, which are surprising in two ways: how loosely defined they are and how many types there are. The type name itself is made up of one or more parts: Part Meaning signed, unsigned, If the type is signed or not. None means or none signed. short, long, long Size classification of the integer. Not an long, or none exact size! None means int. Explicitly state that this is an integer. None int or none states this implicitly. Here’s all 24 permutations, including the sizes in bits on common platforms: C# Type C++ Type Windows Size Unix Size short short 16 16 short short int 16 16 short signed short 16 16 short signed short int 16 16 ushort unsigned short 16 16 ushort unsigned short int 16 16 C# Type C++ Type Windows Size Unix Size int int 32 32 int signed 32 32 int signed int 32 32 uint unsigned 32 32 uint unsigned int 32 32 N/A long 32 64 N/A long int 32 64 N/A long int 32 64 N/A signed long 32 64 N/A signed long int 32 64 N/A unsigned long 32 64 N/A unsigned long int 32 64 long long long 64 64 long long long int 64 64 long signed long long 64 64 long signed long long int 64 64 ulong unsigned long long 64 64 ulong unsigned long long int 64 64 There is also a type called size_t which is either a 32-bit or 64-bit unsigned integer, depending on the CPU being compiled for. There are four 8-bit types: C# Type C++ Type x86 and x64 ARM bool bool N/A N/A sbyte char Signed Unsigned sbyte signed char Signed Signed byte unsigned char Signed Signed The types named with char are due to their original usage for characters in ASCII strings. There are also larger character types: C# Type C++ Type Windows Size Unix Size N/A char8_t 8 8 N/A char16_t 16 16 N/A char32_t 32 32 N/A wchar_t 16 32 Next we have floating-point types, including a super high precision long double type: C# Type C++ Type x86 Size ARM Size float float 32 32 double double 64 32 N/A long double 80 128 There is no decimal type in C++, but libraries such as GMP provide similar functionality. Given the uncertainty of size across CPU and OS, it’s a best practice to avoid many of these types and instead use types that have specific sizes. These are found in the Standard Library or in game engine APIs. Here’s how much simpler that makes everything: Meaning C# Type C++ Type Unreal Type Boolean bool bool bool 8-bit signed integer sbyte int8_t int8 8-bit unsigned integer byte uint8_t uint8 16-bit signed integer short int16_t int16 16-bit unsigned integer ushort uint16_t uint16 8-bit character N/A char8_t CHAR8 16-bit character char char16_t CHAR16 32-bit character N/A char32_t CHAR32 32-bit signed integer int int32_t int32 32-bit unsigned integer uint uint32_t uint32 64-bit signed integer long int64_t int64 64-bit unsigned integer ulong uint64_t uint64 32-bit floating point number float float float 128-bit floating point number decimal N/A N/A Literals Now that we know all these types, let’s express them by writing some literals.