0% found this document useful (0 votes)
9 views

Book1 Getting Started With Modern CPP

The document is a comprehensive handbook titled 'Getting Started with Modern C++' aimed at absolute beginners. It covers various aspects of C++, including its history, environment setup, basic syntax, and control flow, with detailed sections on compilers, IDEs, and writing basic programs. The content is structured to facilitate learning through a progressive approach to modern C++ features and practices.

Uploaded by

lpukiran7
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views

Book1 Getting Started With Modern CPP

The document is a comprehensive handbook titled 'Getting Started with Modern C++' aimed at absolute beginners. It covers various aspects of C++, including its history, environment setup, basic syntax, and control flow, with detailed sections on compilers, IDEs, and writing basic programs. The content is structured to facilitate learning through a progressive approach to modern C++ features and practices.

Uploaded by

lpukiran7
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 166

Modern C++ Handbooks:

Getting Started with Modern C++

Prepared by Ayman Alheraki


Target Audience: Absolute beginners
simplifycpp.org

January 2025
Contents

Contents 2

Modern C++ Handbooks 9

1 Introduction to C++ 21
1.1 What is C++? Why use Modern C++? . . . . . . . . . . . . . . . . . . . . . . 21
1.1.1 What is C++? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.1.2 Why Use Modern C++? . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.1.3 When to Use Modern C++? . . . . . . . . . . . . . . . . . . . . . . . 26
1.1.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
1.2 History of C++ and the Evolution of Standards (C++11 to C++23) . . . . . . . 28
1.2.1 The Origins of C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.2.2 The Evolution of C++ Standards . . . . . . . . . . . . . . . . . . . . . 29
1.2.3 The Impact of Modern C++ Standards . . . . . . . . . . . . . . . . . . 35
1.2.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

2 Setting Up the Environment 36


2.1 Installing a Modern C++ Compiler (GCC, Clang, MSVC) . . . . . . . . . . . . 36
2.1.1 Introduction to C++ Compilers . . . . . . . . . . . . . . . . . . . . . . 36
2.1.2 Installing GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

2
3

2.1.3 Installing Clang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38


2.1.4 Installing MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.1.5 Verifying the Installation . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.1.6 Choosing the Right Compiler . . . . . . . . . . . . . . . . . . . . . . 42
2.1.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
2.2 Setting Up an IDE (Visual Studio, CLion, VS Code) . . . . . . . . . . . . . . . 43
2.2.1 Introduction to IDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.2.2 Setting Up Visual Studio . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.2.3 Setting Up CLion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
2.2.4 Setting Up VS Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.2.5 Choosing the Right IDE . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.2.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.3 Using CMake for Project Management . . . . . . . . . . . . . . . . . . . . . . 50
2.3.1 Introduction to CMake . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.3.2 Installing CMake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.3.3 Creating a Simple CMake Project . . . . . . . . . . . . . . . . . . . . 51
2.3.4 Building the Project with CMake . . . . . . . . . . . . . . . . . . . . 53
2.3.5 Advanced CMake Features . . . . . . . . . . . . . . . . . . . . . . . . 55
2.3.6 Integrating CMake with IDEs . . . . . . . . . . . . . . . . . . . . . . 56
2.3.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

3 Writing Your First Program 58


3.1 Hello World in Modern C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.1.1 Introduction to the ”Hello, World!” Program . . . . . . . . . . . . . . 58
3.1.2 Writing the ”Hello, World!” Program . . . . . . . . . . . . . . . . . . 58
3.1.3 Compiling and Running the Program . . . . . . . . . . . . . . . . . . 60
3.1.4 Modern C++ Features in the ”Hello, World!” Program . . . . . . . . . 61
3.1.5 Enhancing the ”Hello, World!” Program . . . . . . . . . . . . . . . . . 62
4

3.1.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
3.2 Understanding main(), #include, and using namespace std . . . . 64
3.2.1 The main() Function . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.2.2 The #include Directive . . . . . . . . . . . . . . . . . . . . . . . . 65
3.2.3 The using namespace std; Directive . . . . . . . . . . . . . . . 66
3.2.4 Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.2.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

4 Basic Syntax and Structure 70


4.1 Variables and Data Types (int, double, bool, auto) . . . . . . . . . . . . 70
4.1.1 Introduction to Variables and Data Types . . . . . . . . . . . . . . . . 70
4.1.2 Declaring and Initializing Variables . . . . . . . . . . . . . . . . . . . 70
4.1.3 Fundamental Data Types . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.1.4 The auto Keyword . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.1.5 Type Modifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.1.6 Type Conversion and Casting . . . . . . . . . . . . . . . . . . . . . . 74
4.1.7 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.8 Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.1.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4.2 Input and Output (std::cin, std::cout) . . . . . . . . . . . . . . . . . . 77
4.2.1 Introduction to Input and Output in C++ . . . . . . . . . . . . . . . . . 77
4.2.2 The std::cout Object . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.2.3 The std::cin Object . . . . . . . . . . . . . . . . . . . . . . . . . . 78
4.2.4 Handling Input Errors . . . . . . . . . . . . . . . . . . . . . . . . . . 80
4.2.5 Formatted Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
4.2.6 Putting It All Together . . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.2.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
4.3 Operators (Arithmetic, Logical, Relational) . . . . . . . . . . . . . . . . . . . 85
5

4.3.1 Introduction to Operators . . . . . . . . . . . . . . . . . . . . . . . . . 85


4.3.2 Arithmetic Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.3.3 Relational Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
4.3.4 Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.3.5 Combining Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.3.6 Operator Precedence and Associativity . . . . . . . . . . . . . . . . . 90
4.3.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

5 Control Flow 92
5.1 if, else, switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
5.1.1 Introduction to Control Flow . . . . . . . . . . . . . . . . . . . . . . . 92
5.1.2 The if Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
5.1.3 Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.1.4 The if-else if-else Statement . . . . . . . . . . . . . . . . . . 95
5.1.5 The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . 96
5.1.6 Nested Conditional Statements . . . . . . . . . . . . . . . . . . . . . . 98
5.1.7 Best Practices for Conditional Statements . . . . . . . . . . . . . . . . 100
5.1.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.2 Loops (for, while, do-while) . . . . . . . . . . . . . . . . . . . . . . . . 101
5.2.1 Introduction to Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.2.2 The for Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
5.2.3 The while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.2.4 The do-while Loop . . . . . . . . . . . . . . . . . . . . . . . . . . 105
5.2.5 Loop Control Statements . . . . . . . . . . . . . . . . . . . . . . . . . 106
5.2.6 Nested Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
5.2.7 Best Practices for Loops . . . . . . . . . . . . . . . . . . . . . . . . . 108
5.2.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
6

6 Functions 110
6.1 Defining and Calling Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 110
6.1.1 Introduction to Functions . . . . . . . . . . . . . . . . . . . . . . . . . 110
6.1.2 Defining a Function . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
6.1.3 Calling a Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
6.1.4 Function Parameters and Arguments . . . . . . . . . . . . . . . . . . . 112
6.1.5 Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
6.1.6 Function Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
6.1.7 Default Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
6.1.8 Function Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . 116
6.1.9 Inline Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
6.1.10 Best Practices for Functions . . . . . . . . . . . . . . . . . . . . . . . 118
6.1.11 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.2 Function Parameters and Return Values . . . . . . . . . . . . . . . . . . . . . 120
6.2.1 Introduction to Function Parameters and Return Values . . . . . . . . . 120
6.2.2 Function Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
6.2.3 Passing Arguments to Functions . . . . . . . . . . . . . . . . . . . . . 121
6.2.4 Return Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
6.2.5 Passing Parameters by Value vs. by Reference . . . . . . . . . . . . . . 124
6.2.6 Default Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
6.2.7 Returning Multiple Values . . . . . . . . . . . . . . . . . . . . . . . . 126
6.2.8 Best Practices for Parameters and Return Values . . . . . . . . . . . . 128
6.2.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.3 Inline Functions and constexpr . . . . . . . . . . . . . . . . . . . . . . . . 130
6.3.1 Introduction to Inline Functions and constexpr . . . . . . . . . . . 130
6.3.2 Inline Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.3.3 constexpr Functions . . . . . . . . . . . . . . . . . . . . . . . . . 131
7

6.3.4 Combining inline and constexpr . . . . . . . . . . . . . . . . . 133


6.3.5 Practical Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
6.3.6 Best Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.3.7 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136

7 Practical Examples 137


7.1 Simple Programs to Reinforce Concepts . . . . . . . . . . . . . . . . . . . . . 137
7.1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.1.2 Calculator Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.1.3 Number Guessing Game . . . . . . . . . . . . . . . . . . . . . . . . . 140
7.1.4 Best Practices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
7.1.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142

8 Debugging and version control 143


8.1 Debugging Basics (Using GDB or IDE Debuggers) . . . . . . . . . . . . . . . 143
8.1.1 Introduction to Debugging . . . . . . . . . . . . . . . . . . . . . . . . 143
8.1.2 Debugging with GDB . . . . . . . . . . . . . . . . . . . . . . . . . . 143
8.1.3 Debugging with IDE Debuggers . . . . . . . . . . . . . . . . . . . . . 146
8.1.4 Common Debugging Techniques . . . . . . . . . . . . . . . . . . . . . 148
8.1.5 Best Practices for Debugging . . . . . . . . . . . . . . . . . . . . . . . 149
8.1.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
8.2 Introduction to Version Control (Git) . . . . . . . . . . . . . . . . . . . . . . . 150
8.2.1 Introduction to Version Control . . . . . . . . . . . . . . . . . . . . . 150
8.2.2 Why Use Version Control? . . . . . . . . . . . . . . . . . . . . . . . . 150
8.2.3 Installing Git . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
8.2.4 Basic Git Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.2.5 Basic Git Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.2.6 Setting Up a Git Repository . . . . . . . . . . . . . . . . . . . . . . . 152
8

8.2.7 Basic Git Workflow . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153


8.2.8 Branching and Merging . . . . . . . . . . . . . . . . . . . . . . . . . 154
8.2.9 Remote Repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
8.2.10 Best Practices for Using Git . . . . . . . . . . . . . . . . . . . . . . . 155
8.2.11 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

Appendices 156
Appendix A: C++ Standards Overview . . . . . . . . . . . . . . . . . . . . . . . . . 156
Appendix B: Compiler Installation Guidesw . . . . . . . . . . . . . . . . . . . . . . 156
Appendix C: IDE Setup Guides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Appendix D: CMake Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
Appendix E: Debugging Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Appendix F: Git Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Appendix G: Additional Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
Appendix H: Sample Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160

References 162
Modern C++ Handbooks

Introduction to the Modern C++ Handbooks Series


I am pleased to present this series of booklets, compiled from various sources, including books,
websites, and GenAI (Generative Artificial Intelligence) systems, to serve as a quick reference
for simplifying the C++ language for both beginners and professionals. This series consists of
10 booklets, each approximately 150 pages, covering essential topics of this powerful language,
ranging from beginner to advanced levels. I hope that this free series will provide significant
value to the followers of https://simplifycpp.org and align with its strategy of simplifying C++.
Below is the index of these booklets, which will be included at the beginning of each booklet.

Book 1: Getting Started with Modern C++


• Target Audience: Absolute beginners.

• Content:

– Introduction to C++:

* What is C++? Why use Modern C++?


* History of C++ and the evolution of standards (C++11 to C++23).
– Setting Up the Environment:

* Installing a modern C++ compiler (GCC, Clang, MSVC).

9
10

* Setting up an IDE (Visual Studio, CLion, VS Code).


* Using CMake for project management.

– Writing Your First Program:

* Hello World in Modern C++.


* Understanding main(), #include, and using namespace std.

– Basic Syntax and Structure:

* Variables and data types (int, double, bool, auto).


* Input and output (std::cin, std::cout).
* Operators (arithmetic, logical, relational).

– Control Flow:

* if, else, switch.


* Loops (for, while, do-while).

– Functions:

* Defining and calling functions.


* Function parameters and return values.
* Inline functions and constexpr.

– Practical Examples:

* Simple programs to reinforce concepts (e.g., calculator, number guessing game).

– Debugging and Version Control:

* Debugging basics (using GDB or IDE debuggers).


* Introduction to version control (Git).
11

Book 2: Core Modern C++ Features (C++11 to C++23)


• Target Audience: Beginners and intermediate learners.

• Content:

– C++11 Features:

* auto keyword for type inference.


* Range-based for loops.
* nullptr for null pointers.
* Uniform initialization ({} syntax).
* constexpr for compile-time evaluation.
* Lambda expressions.
* Move semantics and rvalue references (std::move, std::forward).
– C++14 Features:

* Generalized lambda captures.


* Return type deduction for functions.
* Relaxed constexpr restrictions.
– C++17 Features:

* Structured bindings.
* if and switch with initializers.
* inline variables.
* Fold expressions.
– C++20 Features:

* Concepts and constraints.


12

* Ranges library.
* Coroutines.
* Three-way comparison (<=> operator).
– C++23 Features:

* std::expected for error handling.


* std::mdspan for multidimensional arrays.
* std::print for formatted output.
– Practical Examples:

* Programs demonstrating each feature (e.g., using lambdas, ranges, and


coroutines).

– Features and Performance :

* Best practices for using Modern C++ features.


* Performance implications of Modern C++.

Book 3: Object-Oriented Programming (OOP) in Modern C++


• Target Audience: Intermediate learners.

• Content:

– Classes and Objects:

* Defining classes and creating objects.


* Access specifiers (public, private, protected).
– Constructors and Destructors:

* Default, parameterized, and copy constructors.


13

* Move constructors and assignment operators.


* Destructors and RAII (Resource Acquisition Is Initialization).
– Inheritance and Polymorphism:

* Base and derived classes.


* Virtual functions and overriding.
* Abstract classes and interfaces.
– Advanced OOP Concepts:

* Multiple inheritance and virtual base classes.


* override and final keywords.
* CRTP (Curiously Recurring Template Pattern).
– Practical Examples:

* Designing a class hierarchy (e.g., shapes, vehicles).


– Design patterns:

* Design patterns in Modern C++ (e.g., Singleton, Factory, Observer).

Book 4: Modern C++ Standard Library (STL)


• Target Audience: Intermediate learners.

• Content:

– Containers:

* Sequence containers (std::vector, std::list, std::deque).


* Associative containers (std::map, std::set, std::unordered map).
14

* Container adapters (std::stack, std::queue,


std::priority queue).

– Algorithms:

* Sorting, searching, and modifying algorithms.


* Parallel algorithms (C++17).
– Utilities:

* Smart pointers (std::unique ptr, std::shared ptr,


std::weak ptr).

* std::optional, std::variant, std::any.


* std::function and std::bind.
– Iterators and Ranges:

* Iterator categories.
* Ranges library (C++20).
– Practical Examples:

* Programs using STL containers and algorithms (e.g., sorting, searching).


– Allocators and Benchmarks :

* Custom allocators.
* Performance benchmarks.

Book 5: Advanced Modern C++ Techniques


• Target Audience: Advanced learners and professionals.

• Content:
15

– Templates and Metaprogramming:

* Function and class templates.


* Variadic templates.
* Type traits and std::enable if.
* Concepts and constraints (C++20).
– Concurrency and Parallelism:

* Threading (std::thread, std::async).


* Synchronization (std::mutex, std::atomic).
* Coroutines (C++20).
– Error Handling:

* Exceptions and noexcept.


* std::optional, std::expected (C++23).
– Advanced Libraries:

* Filesystem library (std::filesystem).


* Networking (C++20 and beyond).
– Practical Examples:

* Advanced programs (e.g., multithreaded applications, template


metaprogramming).
– Lock-free and Memory Management:

* Lock-free programming.
* Custom memory management.

Book 6: Modern C++ Best Practices and Principles


• Target Audience: Professionals.
16

• Content:

– Code Quality:

* Writing clean and maintainable code.


* Naming conventions and coding standards.

– Performance Optimization:

* Profiling and benchmarking.


* Avoiding common pitfalls (e.g., unnecessary copies).

– Design Principles:

* SOLID principles in Modern C++.


* Dependency injection.

– Testing and Debugging:

* Unit testing with frameworks (e.g., Google Test).


* Debugging techniques and tools.

– Security:

* Secure coding practices.


* Avoiding vulnerabilities (e.g., buffer overflows).

– Practical Examples:

* Case studies of well-designed Modern C++ projects.

– Deployment (CI/CD):

* Continuous integration and deployment (CI/CD).


17

Book 7: Specialized Topics in Modern C++


• Target Audience: Professionals.

• Content:

– Scientific Computing:

* Numerical methods and libraries (e.g., Eigen, Armadillo).


* Parallel computing (OpenMP, MPI).
– Game Development:

* Game engines and frameworks.


* Graphics programming (Vulkan, OpenGL).
– Embedded Systems:

* Real-time programming.
* Low-level hardware interaction.
– Practical Examples:

* Specialized applications (e.g., simulations, games, embedded systems).


– Optimizations:

* Domain-specific optimizations.

Book 8: The Future of C++ (Beyond C++23)


• Target Audience: Professionals and enthusiasts.

• Content:
18

– Upcoming features in C++26 and beyond.


– Reflection and metaclasses.
– Advanced concurrency models.
– Experimental and Developments:

* Experimental features and proposals.


* Community trends and developments.

Book 9: Advanced Topics in Modern C++


• Target Audience: Experts and professionals.

• Content:

– Template Metaprogramming:

* SFINAE and std::enable if.


* Variadic templates and parameter packs.
* Compile-time computations with constexpr.
– Advanced Concurrency:

* Lock-free data structures.


* Thread pools and executors.
* Real-time concurrency.
– Memory Management:

* Custom allocators.
* Memory pools and arenas.
* Garbage collection techniques.
19

– Performance Tuning:

* Cache optimization.
* SIMD (Single Instruction, Multiple Data) programming.
* Profiling and benchmarking tools.
– Advanced Libraries:

* Boost library overview.


* GPU programming (CUDA, SYCL).
* Machine learning libraries (e.g., TensorFlow C++ API).
– Practical Examples:

* High-performance computing (HPC) applications.


* Real-time systems and embedded applications.
– C++ projects:

* Case studies of cutting-edge C++ projects.

Book 10: Modern C++ in the Real World


• Target Audience: Professionals.

• Content:

– Case Studies:

* Real-world applications of Modern C++ (e.g., game engines, financial systems,


scientific simulations).

– Industry Best Practices:

* How top companies use Modern C++.


20

* Lessons from large-scale C++ projects.


– Open Source Contributions:

* Contributing to open-source C++ projects.


* Building your own C++ libraries.
– Career Development:

* Building a portfolio with Modern C++.


* Preparing for C++ interviews.
– Networking and conferences :

* Networking with the C++ community.


* Attending conferences and workshops.
Chapter 1

Introduction to C++

1.1 What is C++? Why use Modern C++?

1.1.1 What is C++?

C++ is a general-purpose programming language that combines the efficiency and low-level
capabilities of C with advanced features like object-oriented programming (OOP), generic
programming, and functional programming. It was created by Bjarne Stroustrup in 1979 at
Bell Labs as an extension of the C programming language. Stroustrup's goal was to add OOP
features to C while maintaining its performance and flexibility. Over the decades, C++ has
evolved into one of the most widely used programming languages in the world, powering
everything from operating systems and game engines to scientific simulations and financial
systems.

1. The Philosophy of C++

C++ is built on a few core principles:

21
22

(a) Efficiency: C++ allows developers to write highly optimized code with fine-grained
control over system resources.
(b) Flexibility: It supports multiple programming paradigms, enabling developers to
choose the best approach for their problem.
(c) Compatibility: C++ maintains backward compatibility with C and older C++
standards, allowing gradual adoption of new features.
(d) Abstraction: It provides powerful abstraction mechanisms (e.g., classes, templates)
to manage complexity in large systems.

2. Key Features of C++


C++ is known for its rich set of features, including:

(a) Object-Oriented Programming (OOP):

• Classes and objects.


• Inheritance and polymorphism.
• Encapsulation and abstraction.

(b) Generic Programming:

• Templates for writing reusable code.


• Standard Template Library (STL) for containers and algorithms.

(c) Low-Level Manipulation:

• Pointers and manual memory management.


• Direct access to hardware and system resources.

(d) Standard Library:

• A comprehensive library for data structures, algorithms, and utilities.

(e) Cross-Platform Compatibility:


23

• C++ code can be compiled and run on various platforms, including Windows,
Linux, macOS, and embedded systems.

1.1.2 Why Use Modern C++?


Modern C++ refers to the features and best practices introduced in C++11, C++14, C++17,
C++20, and C++23. These standards have transformed C++ into a more expressive, safer, and
easier-to-use language while retaining its performance and flexibility. Here are the key reasons
to use Modern C++:

1. Improved Readability and Expressiveness


Modern C++ introduces features that make code more concise and readable:

• auto Keyword:

– Automatically deduces the type of a variable, reducing boilerplate code.

auto x = 42; // x is deduced to be an int


auto name = "C++"; // name is deduced to be a const char*

• Range-Based for Loops:

– Simplifies iteration over containers.

std::vector<int> numbers = {1, 2, 3, 4, 5};


for (const auto& number : numbers) {
std::cout << number << std::endl;
}

• Lambda Expressions:

– Enables writing inline functions, making code more expressive.


24

auto square = [](int x) { return x * x; };


std::cout << square(5) << std::endl; // Output: 25

2. Enhanced Safety and Reliability


Modern C++ includes features that help prevent common programming errors:

• Smart Pointers:
– Automatically manage memory, reducing the risk of memory leaks.

std::unique_ptr<int> ptr = std::make_unique<int>(42);


// No need to manually delete ptr; it will be automatically
,→ cleaned up.

• nullptr:
– Replaces NULL for null pointers, avoiding ambiguity.

int* ptr = nullptr; // ptr is explicitly a null pointer

• Strongly Typed Enums (enum class):


– Prevents implicit conversions, improving type safety.

enum class Color { Red, Green, Blue };


Color color = Color::Red;
// color cannot be implicitly converted to an integer.

3. Better Performance
Modern C++ provides tools to write more efficient code:
25

• Move Semantics:

– Allows transferring resources (e.g., memory) instead of copying them,


improving performance.

std::vector<int> v1 = {1, 2, 3};


std::vector<int> v2 = std::move(v1); // v1 is now empty

• constexpr:

– Enables compile-time evaluation of functions and variables, reducing runtime


overhead.

constexpr int square(int x) { return x * x; }


constexpr int result = square(5); // Evaluated at compile time

4. Modern Features for Modern Problems


Modern C++ introduces features that address contemporary programming challenges:

• Concurrency Support:

– Provides tools for writing multi-threaded and parallel programs.

std::thread t([]() { std::cout << "Hello from thread!" <<


,→ std::endl; });
t.join();

• Coroutines (C++20):

– Simplifies asynchronous programming.


26

std::future<int> result = std::async([]() { return 42; });


std::cout << result.get() << std::endl; // Output: 42

• Concepts (C++20):

– Improves template programming by specifying constraints on template


parameters.

template<typename T>
requires std::integral<T>
T add(T a, T b) { return a + b; }

5. Backward Compatibility
Modern C++ maintains backward compatibility with older C++ standards and C,
allowing developers to gradually adopt new features without rewriting existing code.

6. Community and Ecosystem


Modern C++ has a vibrant community and a rich ecosystem of libraries and tools,
including:

• Boost: A collection of peer-reviewed, high-quality libraries.


• Qt: A framework for building cross-platform applications.
• CMake: A build system for managing complex projects.

1.1.3 When to Use Modern C++?


Modern C++ is suitable for a wide range of applications, including:

• Systems Programming: Operating systems, device drivers, and embedded systems.


27

• Game Development: Game engines and real-time simulations.

• Scientific Computing: Numerical simulations and data analysis.

• Web Servers and Networking: High-performance backend systems.

• Financial Systems: Algorithmic trading and risk analysis.

1.1.4 Summary
C++ is a powerful and versatile programming language that has evolved significantly with the
introduction of Modern C++ standards (C++11 to C++23). These standards have made C++
more expressive, safer, and easier to use while retaining its performance and flexibility. Whether
you're building a high-performance game engine, a real-time operating system, or a scientific
simulation, Modern C++ provides the tools and features you need to write efficient, reliable, and
maintainable code.
28

1.2 History of C++ and the Evolution of Standards (C++11 to


C++23)

1.2.1 The Origins of C++


C++ was created by Bjarne Stroustrup in 1979 at Bell Labs. Stroustrup initially developed C++
as an extension of the C programming language, which was widely used for system
programming. His goal was to add object-oriented programming (OOP) features to C while
retaining its efficiency and low-level capabilities. The language was originally called ”C with
Classes” but was later renamed C++ in 1983, with the ”++” symbol indicating an increment or
improvement over C.

1. The Motivation Behind C++


Stroustrup's motivation for creating C++ stemmed from his experience with Simula, an
early object-oriented language. While Simula introduced powerful OOP concepts, it was
too slow for system-level programming. Stroustrup sought to combine the efficiency of C
with the abstraction and organization of Simula, resulting in a language that could
handle large-scale software projects without sacrificing performance.

2. Early Development and Adoption

• 1979: Stroustrup begins work on ”C with Classes.”


• 1983: The language is renamed to C++.
• 1985: The first commercial release of C++.
• 1989: The C++ 2.0 release introduces features like multiple inheritance and abstract
classes.
• 1998: The first standardized version of C++ (C++98) is published by the ISO/IEC
(International Organization for Standardization).
29

1.2.2 The Evolution of C++ Standards


C++ has undergone significant evolution since its inception, with major updates released every
few years. These updates have introduced new features, improved existing ones, and addressed
the needs of modern software development. Below is a detailed overview of the evolution of
C++ standards from C++11 to C++23.

1. C++11: A Major Leap Forward

Released in 2011, C++11 was a transformative update that introduced many modern
features to the language. It is often referred to as ”Modern C++” and marked the
beginning of a new era for C++.

Key Features of C++11:

(a) auto Keyword:

• Automatically deduces the type of a variable.

auto x = 42; // x is deduced to be an int


auto name = "C++"; // name is deduced to be a const char*

(b) Range-Based for Loops:

• Simplifies iteration over containers.

std::vector<int> numbers = {1, 2, 3, 4, 5};


for (const auto& number : numbers) {
std::cout << number << std::endl;
}

(c) Lambda Expressions:


30

• Enables writing inline functions.

auto square = [](int x) { return x * x; };


std::cout << square(5) << std::endl; // Output: 25

(d) Smart Pointers:


• Automatically manage memory with std::unique ptr,
std::shared ptr, and std::weak ptr.

std::unique_ptr<int> ptr = std::make_unique<int>(42);


// No need to manually delete ptr; it will be automatically
,→ cleaned up.

(e) Move Semantics:


• Allows transferring resources (e.g., memory) instead of copying them.

std::vector<int> v1 = {1, 2, 3};


std::vector<int> v2 = std::move(v1); // v1 is now empty

(f) nullptr:
• Replaces NULL for null pointers, avoiding ambiguity.

int* ptr = nullptr; // ptr is explicitly a null pointer

(g) Concurrency Support:


• Introduces threading (std::thread), mutexes (std::mutex), and futures
(std::future).
31

std::thread t([]() { std::cout << "Hello from thread!" <<


,→ std::endl; });
t.join();

2. C++14: Refinements and Extensions

Released in 2014, C++14 built on the foundation of C++11, refining existing features and
adding new ones to improve usability and performance.

Key Features of C++14:

(a) Generalized Lambda Captures:

• Allows capturing variables by value or reference in lambdas.

int x = 10;
auto lambda = [x]() { return x + 1; };

(b) Return Type Deduction for Functions:

• Automatically deduces the return type of a function.

auto add(int a, int b) { return a + b; }

(c) Relaxed constexpr Restrictions:

• Allows more complex computations in constexpr functions.

constexpr int square(int x) { return x * x; }


32

3. C++17: A Step Toward Modernization

Released in 2017, C++17 introduced features that further modernized the language,
making it more expressive and easier to use.

Key Features of C++17:

(a) Structured Bindings:

• Simplifies unpacking tuples and pairs.

auto [x, y] = std::make_pair(1, 2);

(b) if and switch with Initializers:

• Allows initializing variables within if and switch statements.

if (auto it = map.find(key); it != map.end()) { /* ... */ }

(c) std::optional, std::variant, and std::any:

• Provides safer alternatives to raw pointers and unions.

std::optional<int> result = computeValue();


if (result) { /* ... */ }

(d) Parallel Algorithms:

• Introduces parallel versions of STL algorithms.

std::sort(std::execution::par, vec.begin(), vec.end());


33

4. C++20: A New Era of Modern C++

Released in 2020, C++20 was a major update that introduced groundbreaking features,
making C++ more powerful and expressive than ever before.

Key Features of C++20:

(a) Concepts:

• Improves template programming by specifying constraints on template


parameters.

template<typename T>
requires std::integral<T>
T add(T a, T b) { return a + b; }

(b) Ranges Library:

• Simplifies working with sequences of data.

auto even = std::views::filter([](int x) { return x % 2 == 0; });


for (int x : vec | even) { /* ... */ }

(c) Coroutines:

• Simplifies asynchronous programming.

std::future<int> compute() {
co_return 42;
}

(d) Three-Way Comparison (<=> Operator):


34

• Simplifies comparison operators.

auto cmp = (a <=> b);

5. C++23: The Future of C++

Scheduled for release in 2023, C++23 continues to build on the foundation of C++20,
introducing new features and improvements.

Key Features of C++23:

(a) std::expected:

• Provides a better way to handle errors.

std::expected<int, std::string> result = computeValue();


if (result) { /* ... */ }

(b) std::mdspan:

• Represents multidimensional arrays.

std::mdspan<int, 2> matrix(data, 3, 3);

(c) std::print:

• Simplifies formatted output.

std::print("Hello, {}!", "World");

(d) std::stacktrace:
35

• Provides a way to capture and inspect stack traces.

auto trace = std::stacktrace::current();

1.2.3 The Impact of Modern C++ Standards


The evolution of C++ standards from C++11 to C++23 has transformed the language into a
modern, expressive, and powerful tool for software development. These updates have addressed
the needs of contemporary programming, including:

• Improved Readability: Features like auto, lambdas, and ranges make code more
concise and expressive.

• Enhanced Safety: Smart pointers, nullptr, and std::optional reduce common


programming errors.

• Better Performance: Move semantics, constexpr, and parallel algorithms improve


efficiency.

• Modern Problem-Solving: Concepts, coroutines, and ranges address modern


programming challenges.

1.2.4 Summary
The history of C++ is a story of continuous evolution and improvement. From its origins as ”C
with Classes” to the modern features of C++23, C++ has remained a powerful and versatile
language for a wide range of applications. The introduction of Modern C++ standards (C++11 to
C++23) has made the language more expressive, safer, and easier to use, ensuring its relevance
in the ever-changing world of software development.
Chapter 2

Setting Up the Environment

2.1 Installing a Modern C++ Compiler (GCC, Clang, MSVC)

2.1.1 Introduction to C++ Compilers


A C++ compiler is a program that translates C++ source code into machine code that can be
executed by a computer. Modern C++ compilers support the latest C++ standards (C++11,
C++14, C++17, C++20, and C++23) and provide optimizations, diagnostics, and debugging
tools to help developers write efficient and reliable code.
The three most widely used C++ compilers are:

1. GCC (GNU Compiler Collection): An open-source compiler that supports multiple


programming languages, including C++.

2. Clang: A compiler front-end for the LLVM project, known for its excellent diagnostics
and performance.

3. MSVC (Microsoft Visual C++): The compiler provided by Microsoft as part of the
Visual Studio IDE.

36
37

2.1.2 Installing GCC


GCC is a popular open-source compiler available on Linux, macOS, and Windows (via MinGW
or WSL).

1. Installing GCC on Linux

Most Linux distributions come with GCC pre-installed. To check if GCC is installed and
its version:

g++ --version

If GCC is not installed, you can install it using your distribution's package manager:

• Ubuntu/Debian:

sudo apt update


sudo apt install g++

• Fedora:

sudo dnf install gcc-c++

• Arch Linux:

sudo pacman -S gcc

(a) Installing GCC on macOS


On macOS, GCC can be installed using Homebrew:
38

i. Install Homebrew (if not already installed):

/bin/bash -c "$(curl -fsSL


,→ https://raw.githubusercontent.com/Homebrew/install/HEAD/install.s

ii. Install GCC:

brew install gcc

(b) Installing GCC on Windows


On Windows, GCC can be installed via MinGW or WSL (Windows Subsystem for
Linux):

• MinGW:
i. Download the MinGW installer from MinGW website.
ii. Follow the installation instructions and select the g++ package.
• WSL:
i. Enable WSL and install a Linux distribution (e.g., Ubuntu) from the
Microsoft Store.
ii. Follow the Linux instructions above to install GCC.

2.1.3 Installing Clang


Clang is known for its fast compilation times and excellent diagnostics. It is available on Linux,
macOS, and Windows.

1. Installing Clang on Linux

Most Linux distributions provide Clang in their package repositories:


39

• Ubuntu/Debian:

sudo apt update


sudo apt install clang

• Fedora:

sudo dnf install clang

• Arch Linux:

sudo pacman -S clang

2. Installing Clang on macOS

Clang is the default compiler on macOS. To check its version:

clang++ --version

To install the latest version using Homebrew:

brew install llvm

3. Installing Clang on Windows

Clang can be installed on Windows via LLVM or WSL:

• LLVM:

(a) Download the LLVM installer from LLVM website.


40

(b) Follow the installation instructions.

• WSL:

(a) Enable WSL and install a Linux distribution (e.g., Ubuntu) from the Microsoft
Store.
(b) Follow the Linux instructions above to install Clang.

2.1.4 Installing MSVC


MSVC is the default compiler for Windows and is included with the Visual Studio IDE.

1. Installing MSVC via Visual Studio

(a) Download Visual Studio from the Visual Studio website.

(b) Run the installer and select the Desktop development with C++ workload.

(c) Ensure that the MSVC component is selected.

(d) Complete the installation and launch Visual Studio.

2. Using MSVC from the Command Line

To use MSVC from the command line:

(a) Open the Developer Command Prompt for Visual Studio.

(b) Check the compiler version:

cl /?
41

2.1.5 Verifying the Installation


After installing a compiler, verify that it works by compiling a simple C++ program:

1. Create a file named hello.cpp:

#include <iostream>
int main() {
std::cout << "Hello, Modern C++!" << std::endl;
return 0;
}

2. Compile the program:

• GCC/Clang:

g++ hello.cpp -o hello

• MSVC:

cl /EHsc hello.cpp

3. Run the program:

• GCC/Clang:

./hello

• MSVC:
42

hello.exe

2.1.6 Choosing the Right Compiler


The choice of compiler depends on your platform and needs:

• GCC: Best for Linux and cross-platform development.

• Clang: Known for fast compilation and excellent diagnostics.

• MSVC: Ideal for Windows development and integration with Visual Studio.

2.1.7 Summary
Installing a modern C++ compiler is the first step toward developing C++ applications. Whether
you choose GCC, Clang, or MSVC, each compiler provides robust support for Modern C++
standards and tools to help you write efficient and reliable code. By following the instructions in
this section, you can set up your development environment and start exploring the power of
Modern C++.
43

2.2 Setting Up an IDE (Visual Studio, CLion, VS Code)

2.2.1 Introduction to IDEs


An Integrated Development Environment (IDE) is a software application that provides
comprehensive facilities for software development. It typically includes a code editor,
compiler, debugger, and other tools to streamline the development process. For C++
development, using an IDE can significantly improve productivity by providing features like
syntax highlighting, code completion, and integrated debugging.
The three most popular IDEs for C++ development are:

1. Visual Studio: A powerful IDE from Microsoft, ideal for Windows development.

2. CLion: A cross-platform IDE from JetBrains, known for its intelligent code analysis.

3. VS Code: A lightweight, extensible code editor from Microsoft, with support for C++ via
extensions.

2.2.2 Setting Up Visual Studio


Visual Studio is a feature-rich IDE that supports C++ development on Windows. It includes the
MSVC compiler and a wide range of tools for debugging, profiling, and testing.

1. Installing Visual Studio

(a) Download Visual Studio:

• Visit the Visual Studio website.


• Download the Community edition (free for individual developers).

(b) Run the Installer:


44

• Launch the installer and select the Desktop development with C++ workload.
• Ensure that the MSVC compiler and Windows SDK are selected.
(c) Complete the Installation:
• Follow the on-screen instructions to complete the installation.
• Launch Visual Studio after installation.

2. Creating a C++ Project

(a) Open Visual Studio:


• Launch Visual Studio and click on Create a new project.
(b) Select Project Type:
• Choose Console App under the C++ category.
(c) Configure Project:
• Enter a project name and location.
• Click Create to generate the project.
(d) Write and Run Code:
• Open the main.cpp file and write your C++ code.
• Press F5 to build and run the project.

3. Configuring Visual Studio

• Enable Modern C++ Features:


– Go to Project Properties > C/C++ > Language.
– Set the C++ Language Standard to C++20 or C++23.
• Install Extensions:
– Use the Extensions Manager to install additional tools like ReSharper C++
for enhanced code analysis.
45

2.2.3 Setting Up CLion


CLion is a cross-platform IDE from JetBrains that provides advanced code analysis and
refactoring tools for C++ development.

1. Installing CLion

(a) Download CLion:

• Visit the CLion website.


• Download the installer for your operating system.

(b) Run the Installer:

• Follow the on-screen instructions to install CLion.


• Launch CLion after installation.

2. Creating a C++ Project

(a) Open CLion:

• Launch CLion and click on New Project.

(b) Select Project Type:

• Choose C++ Executable.

(c) Configure Project:

• Enter a project name and location.


• Select the C++ Standard (e.g., C++20).
• Click Create to generate the project.

(d) Write and Run Code:

• Open the main.cpp file and write your C++ code.


46

• Press Shift + F10 to build and run the project.

3. Configuring CLion

• Set Up Compiler:

– Go to File > Settings > Build, Execution, Deployment > Toolchains.


– Configure the compiler (e.g., GCC, Clang) and ensure it supports the desired
C++ standard.

• Enable Code Analysis:

– Use the built-in code analysis tools to detect issues and improve code quality.

2.2.4 Setting Up VS Code


VS Code is a lightweight, extensible code editor that can be configured for C++ development
using extensions.

1. Installing VS Code

(a) Download VS Code:

• Visit the VS Code website.


• Download the installer for your operating system.

(b) Run the Installer:

• Follow the on-screen instructions to install VS Code.


• Launch VS Code after installation.

2. Installing C++ Extensions

(a) Open Extensions Marketplace:


47

• Click on the Extensions icon in the Activity Bar or press Ctrl + Shift +
X.

(b) Install C++ Extension:

• Search for C/C++ and install the extension provided by Microsoft.

(c) Install Other Useful Extensions:

• CMake Tools: For CMake integration.


• Code Runner: For running code snippets.
• Clang-Format: For code formatting.

3. Configuring VS Code for C++

(a) Create a C++ Project:

• Create a new folder for your project and open it in VS Code.


• Add a main.cpp file and write your C++ code.

(b) Configure Build Tasks:

• Go to Terminal > Configure Default Build Task.


• Select C/C++: g++ build active file (or the appropriate compiler).

(c) Run and Debug Code:

• Press Ctrl + F5 to run the code.


• Use the Debug panel to set breakpoints and debug your code.

4. Using CMake with VS Code

(a) Install CMake:

• Download and install CMake from the CMake website.


48

(b) Create a CMake Project:

• Create a CMakeLists.txt file in your project folder.


• Example CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(MyProject)
set(CMAKE_CXX_STANDARD 20)
add_executable(MyProject main.cpp)

(c) Configure CMake in VS Code:

• Open the Command Palette (Ctrl + Shift + P) and select CMake:


Configure.
• Select your compiler and build the project.

2.2.5 Choosing the Right IDE


The choice of IDE depends on your platform and preferences:

• Visual Studio: Best for Windows development with deep integration with MSVC.

• CLion: Ideal for cross-platform development with advanced code analysis.

• VS Code: Lightweight and extensible, suitable for developers who prefer a customizable
environment.

2.2.6 Summary
Setting up an IDE is a crucial step in creating a productive C++ development environment.
Whether you choose Visual Studio, CLion, or VS Code, each IDE provides powerful tools and
features to help you write, debug, and optimize Modern C++ code. By following the instructions
49

in this section, you can configure your preferred IDE and start building C++ applications with
confidence.
50

2.3 Using CMake for Project Management

2.3.1 Introduction to CMake


CMake is an open-source, cross-platform build system generator that simplifies the process of
building, testing, and packaging software. It allows developers to describe their build
configuration in a platform-independent way using a high-level scripting language. CMake
generates native build files (e.g., Makefiles, Visual Studio projects) that can be used to compile
and link C++ projects.

1. Why Use CMake?

• Cross-Platform: CMake supports multiple platforms, including Windows, Linux,


and macOS.

• Scalability: It is suitable for both small and large projects.

• Integration: CMake integrates with IDEs (e.g., Visual Studio, CLion) and build
tools (e.g., Make, Ninja).

• Modularity: CMake allows you to organize your project into reusable modules and
libraries.

2.3.2 Installing CMake


Before using CMake, you need to install it on your system.

1. Installing CMake on Linux

Most Linux distributions provide CMake in their package repositories:

• Ubuntu/Debian:
51

sudo apt update


sudo apt install cmake

• Fedora:

sudo dnf install cmake

• Arch Linux:

sudo pacman -S cmake

2. Installing CMake on macOS

On macOS, CMake can be installed using Homebrew:

brew install cmake

3. Installing CMake on Windows

On Windows, CMake can be installed via the official installer:

(a) Download the installer from the CMake website.

(b) Run the installer and follow the on-screen instructions.

(c) Ensure that CMake is added to your system PATH.

2.3.3 Creating a Simple CMake Project


Let's create a simple C++ project using CMake.
52

1. Project Structure
A typical CMake project has the following structure:

MyProject/
CMakeLists.txt
include/
MyLibrary.h
src/
MyLibrary.cpp
main.cpp

2. Writing the CMakeLists.txt File


The CMakeLists.txt file is the core configuration file for CMake. Here's an example
for a simple project:

# Minimum required version of CMake


cmake_minimum_required(VERSION 3.10)

# Project name and version


project(MyProject VERSION 1.0)

# Set the C++ standard


set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# Add an executable
add_executable(MyProject src/main.cpp src/MyLibrary.cpp)

# Include directories
target_include_directories(MyProject PUBLIC include)
53

3. Writing the Source Code

• include/MyLibrary.h:

#ifndef MYLIBRARY_H
#define MYLIBRARY_H

void printMessage();

#endif // MYLIBRARY_H

• src/MyLibrary.cpp:

#include "MyLibrary.h"
#include <iostream>

void printMessage() {
std::cout << "Hello from MyLibrary!" << std::endl;
}

• src/main.cpp:

#include "MyLibrary.h"

int main() {
printMessage();
return 0;
}

2.3.4 Building the Project with CMake


1. Generating Build Files
54

(a) Create a Build Directory:

• Navigate to your project directory and create a build folder:

mkdir build
cd build

(b) Generate Build Files:

• Run CMake to generate the build files:

cmake ..

2. Building the Project

• Linux/macOS:

make

• Windows (Visual Studio):


Open the generated .sln file in Visual Studio and build the project.

3. Running the Executable

• Linux/macOS:

./MyProject

• Windows:
Run the generated .exe file from the command line or Visual Studio.
55

2.3.5 Advanced CMake Features


1. Adding Libraries
To add a library to your project:

# Add a library
add_library(MyLibrary src/MyLibrary.cpp)

# Link the library to the executable


target_link_libraries(MyProject MyLibrary)

2. Using External Libraries


To use an external library (e.g., Boost):

# Find the Boost library


find_package(Boost REQUIRED COMPONENTS filesystem)

# Link the library to the executable


target_link_libraries(MyProject Boost::filesystem)

3. Configuring Compiler Options


To set compiler options:

# Enable warnings
target_compile_options(MyProject PRIVATE -Wall -Wextra -pedantic)

4. Installing the Project


To install the project:
56

# Install the executable


install(TARGETS MyProject DESTINATION bin)

# Install the headers


install(DIRECTORY include/ DESTINATION include)

Run the following command to install:

cmake --install .

2.3.6 Integrating CMake with IDEs


1. Visual Studio

• Open the CMakeLists.txt file in Visual Studio.

• Visual Studio will automatically configure the project.

2. CLion

• Open the project directory in CLion.

• CLion will detect the CMakeLists.txt file and configure the project.

3. VS Code

• Install the CMake Tools extension.

• Open the project directory in VS Code.

• Use the CMake Tools extension to configure and build the project.
57

2.3.7 Summary
CMake is a powerful and flexible tool for managing C++ projects. It simplifies the build process,
supports cross-platform development, and integrates with popular IDEs. By following the
instructions in this section, you can set up and manage your C++ projects using CMake,
ensuring a consistent and efficient development workflow.
Chapter 3

Writing Your First Program

3.1 Hello World in Modern C++

3.1.1 Introduction to the ”Hello, World!” Program


The ”Hello, World!” program is a traditional starting point for learning a new programming
language. It is a simple program that outputs the text ”Hello, World!” to the console. In this
section, we will write a ”Hello, World!” program using Modern C++ features and explore the
key components of the program.

3.1.2 Writing the ”Hello, World!” Program


Let's start by writing the ”Hello, World!” program in Modern C++.

1. The Code

Here is the complete code for the ”Hello, World!” program:

58
59

#include <iostream>

int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}

2. Explanation of the Code

(a) #include <iostream>:

• This line includes the Input/Output Stream Library, which provides


functionality for input and output operations. The iostream library includes
the std::cout object, which is used to print text to the console.

(b) int main() { ... }:

• This is the main function, which is the entry point of every C++ program. The
program execution begins here.
• The int return type indicates that the function returns an integer value. By
convention, returning 0 indicates that the program executed successfully.

(c) std::cout << "Hello, World!" << std::endl;:

• std::cout is the standard output stream object, used to print text to the
console.
• The << operator is the insertion operator, which sends the text ”Hello,
World!” to the output stream.
• std::endl is a manipulator that inserts a newline character and flushes the
output buffer.

(d) return 0;:


60

• This statement ends the main function and returns the value 0 to the operating
system, indicating that the program completed successfully.

3.1.3 Compiling and Running the Program


Now that we have written the ”Hello, World!” program, let's compile and run it.

1. Compiling the Program

To compile the program, you need a C++ compiler such as GCC, Clang, or MSVC.

(a) Save the Code:

• Save the code in a file named hello.cpp.

(b) Compile the Code:

• Open a terminal or command prompt and navigate to the directory containing


hello.cpp.
• Use the following command to compile the program:
– GCC/Clang:

g++ hello.cpp -o hello

– MSVC:

cl /EHsc hello.cpp

2. Running the Program

After compiling the program, you can run it as follows:


61

• Linux/macOS:

./hello

• Windows:

hello.exe

The output will be:

Hello, World!

3.1.4 Modern C++ Features in the ”Hello, World!” Program


While the ”Hello, World!” program is simple, it already incorporates some Modern C++ features
and best practices:

1. Standard Library Usage:

• The program uses the std::cout and std::endl objects from the C++
Standard Library, which are part of Modern C++.

2. Namespaces:

• The std:: prefix indicates that cout and endl are part of the std namespace,
which is a Modern C++ feature for organizing code and avoiding name conflicts.

3. Return Type:

• The int return type of the main function is a standard practice in Modern C++.
62

3.1.5 Enhancing the ”Hello, World!” Program


Let's enhance the ”Hello, World!” program by adding some Modern C++ features.

1. Using auto for Type Inference

We can use the auto keyword to automatically deduce the type of a variable:

#include <iostream>

int main() {
auto message = "Hello, World!";
std::cout << message << std::endl;
return 0;
}

2. Using Range-Based for Loop

We can use a range-based for loop to iterate over a collection:

#include <iostream>
#include <vector>

int main() {
std::vector<std::string> messages = {"Hello,", "World!"};
for (const auto& word : messages) {
std::cout << word << " ";
}
std::cout << std::endl;
return 0;
}
63

3. Using Lambda Expressions


We can use a lambda expression to define a function inline:

#include <iostream>

int main() {
auto printMessage = []() {
std::cout << "Hello, World!" << std::endl;
};
printMessage();
return 0;
}

3.1.6 Summary
The ”Hello, World!” program is a simple yet powerful introduction to Modern C++. It
demonstrates the basic structure of a C++ program, including the use of the Standard Library,
namespaces, and the main function. By enhancing the program with Modern C++ features like
auto, range-based for loops, and lambda expressions, we can explore the expressive power
and flexibility of the language.
This section provides a comprehensive guide to writing, compiling, and running the ”Hello,
World!” program in Modern C++. It also introduces key Modern C++ features and best
practices, setting the stage for more advanced topics in the book.
64

3.2 Understanding main(), #include, and using


namespace std

3.2.1 The main() Function


The main() function is the entry point of every C++ program. It is where the execution of the
program begins and ends. Understanding the structure and purpose of the main() function is
crucial for writing C++ programs.

1. Structure of the main() Function


The main() function has the following structure:

int main() {
// Program code goes here
return 0;
}

• Return Type (int):


– The int return type indicates that the main() function returns an integer
value to the operating system. By convention, returning 0 signifies that the
program executed successfully. Non-zero values typically indicate errors.
• Function Body:
– The code inside the main() function is executed when the program runs. This
is where you write the logic of your program.
• Return Statement (return 0;):
– The return 0; statement ends the main() function and returns the value 0
to the operating system, indicating successful execution.
65

2. Command-Line Arguments
The main() function can also accept command-line arguments, which allow you to pass
parameters to the program when it is executed:

int main(int argc, char* argv[]) {


// argc: Number of command-line arguments
// argv: Array of command-line arguments
for (int i = 0; i < argc; ++i) {
std::cout << "Argument " << i << ": " << argv[i] <<
,→ std::endl;
}
return 0;
}

• argc: The number of command-line arguments.


• argv: An array of C-style strings containing the command-line arguments.

3.2.2 The #include Directive


The #include directive is used to include header files in your C++ program. Header files
contain declarations of functions, classes, and other entities that are defined in libraries or other
source files.

1. Syntax of #include
The #include directive has the following syntax:

#include <header_file>

or
66

#include "header_file"

• Angle Brackets (< >):


– Used for including standard library headers (e.g., <iostream>,
<vector>).

#include <iostream>

• Double Quotes (" "):


– Used for including user-defined headers or local files.

#include "my_header.h"

2. Common Standard Library Headers

• <iostream>: Provides input and output functionality (e.g., std::cout,


std::cin).
• <vector>: Provides the std::vector container for dynamic arrays.
• <string>: Provides the std::string class for string manipulation.
• <algorithm>: Provides common algorithms (e.g., std::sort,
std::find).

3.2.3 The using namespace std; Directive


The using namespace std; directive is used to bring all the names from the std
namespace into the current scope. This allows you to use standard library entities (e.g., cout,
endl) without the std:: prefix.
67

1. Namespaces in C++

• Namespaces: A namespace is a declarative region that provides a scope to the


identifiers (e.g., functions, classes) inside it. The std namespace contains all the
entities of the C++ Standard Library.
• Purpose: Namespaces prevent name conflicts and organize code into logical groups.

2. Using using namespace std;

• Example:

#include <iostream>
using namespace std;

int main() {
cout << "Hello, World!" << endl;
return 0;
}

– Here, cout and endl can be used directly without the std:: prefix.

3. Pros and Cons of using namespace std;

• Pros:

– Reduces verbosity by eliminating the need for the std:: prefix.


– Makes code more readable, especially for beginners.

• Cons:

– Can lead to name conflicts if multiple namespaces are used.


– Reduces clarity about which namespace a particular entity belongs to.
68

4. Best Practices

• Avoid in Header Files: Do not use using namespace std; in header files to
prevent name conflicts in other files that include the header.
• Use in Source Files: It is generally safe to use using namespace std; in
source files, but consider using the std:: prefix for clarity and to avoid potential
conflicts.

3.2.4 Putting It All Together


Let's combine the concepts of main(), #include, and using namespace std in a
complete example:

#include <iostream> // Include the iostream library for input/output


using namespace std; // Bring the std namespace into the current scope

int main() {
// Print "Hello, World!" to the console
cout << "Hello, World!" << endl;

// Return 0 to indicate successful execution


return 0;
}

1. Explanation

(a) #include <iostream>:


• Includes the iostream library, which provides std::cout and
std::endl.
(b) using namespace std;:
69

• Brings all names from the std namespace into the current scope, allowing us to
use cout and endl without the std:: prefix.

(c) int main() { ... }:

• Defines the main() function, which is the entry point of the program.

(d) cout << "Hello, World!" << endl;:

• Uses cout to print ”Hello, World!” to the console and endl to insert a
newline.

(e) return 0;:

• Ends the main() function and returns 0 to indicate successful execution.

3.2.5 Summary
Understanding the main() function, the #include directive, and the using namespace
std; directive is essential for writing and understanding C++ programs. These concepts form
the foundation of C++ programming and are used in virtually every C++ program. By mastering
these basics, you will be well-prepared to explore more advanced topics in Modern C++.
Chapter 4

Basic Syntax and Structure

4.1 Variables and Data Types (int, double, bool, auto)

4.1.1 Introduction to Variables and Data Types

In C++, a variable is a named storage location in memory that holds a value of a specific data
type. Data types define the kind of data a variable can store, such as integers, floating-point
numbers, or boolean values. Understanding variables and data types is fundamental to writing
C++ programs.

4.1.2 Declaring and Initializing Variables

To use a variable in C++, you must first declare it by specifying its data type and name. You can
also initialize the variable by assigning it a value at the time of declaration.

1. Syntax for Declaring Variables

70
71

data_type variable_name;

2. Syntax for Initializing Variables

data_type variable_name = value;

3. Example

int age = 25; // Declare and initialize an integer variable

4.1.3 Fundamental Data Types


C++ provides several fundamental data types, including:

1. int (Integer)

• Description: Represents whole numbers (positive, negative, or zero).

• Size: Typically 4 bytes (32 bits).

• Range: -2,147,483,648 to 2,147,483,647.

• Example:

int count = 10; // Declare and initialize an integer variable

2. double (Double-Precision Floating-Point)

• Description: Represents floating-point numbers with double precision.


72

• Size: Typically 8 bytes (64 bits).

• Range: Approximately ±1.7e308 with 15-17 significant digits.

• Example:

double pi = 3.14159; // Declare and initialize a double variable

3. bool (Boolean)

• Description: Represents boolean values (true or false).

• Size: Typically 1 byte (8 bits).

• Values: true (1) or false (0).

• Example:

bool isReady = true; // Declare and initialize a boolean variable

4.1.4 The auto Keyword


The auto keyword, introduced in C++11, allows the compiler to automatically deduce the type
of a variable based on its initializer. This simplifies code and reduces redundancy.

1. Syntax for auto

auto variable_name = value;

2. Example
73

auto number = 42; // number is deduced to be an int


auto rate = 3.14; // rate is deduced to be a double
auto flag = true; // flag is deduced to be a bool

3. Benefits of auto

• Reduces Redundancy: Eliminates the need to explicitly specify the type.


• Improves Readability: Makes code more concise and easier to read.
• Enhances Maintainability: Reduces the risk of type-related errors.

4. Limitations of auto

• Requires Initialization: The variable must be initialized at the time of declaration.


• Less Explicit: The type is not immediately visible, which can make code harder to
understand in some cases.

4.1.5 Type Modifiers


C++ provides type modifiers that can alter the meaning of the fundamental data types:

1. signed and unsigned

• signed: Allows both positive and negative values (default for int).
• unsigned: Allows only non-negative values.
• Example:

unsigned int positiveNumber = 100; // Can only store non-negative


,→ values
74

2. short and long

• short: Reduces the size of the data type (e.g., short int).
• long: Increases the size of the data type (e.g., long int).
• Example:

short int smallNumber = 32767; // Smaller range than int


long int largeNumber = 2147483647; // Larger range than int

4.1.6 Type Conversion and Casting


C++ supports both implicit and explicit type conversion.

1. Implicit Type Conversion

• Description: Automatically converts one type to another when necessary.


• Example:

int i = 10;
double d = i; // Implicit conversion from int to double

2. Explicit Type Casting

• Description: Manually converts one type to another using casting operators.


• Example:

double d = 3.14;
int i = static_cast<int>(d); // Explicit conversion from double
,→ to int
75

4.1.7 Constants
Constants are variables whose values cannot be changed after initialization. They are declared
using the const keyword.

1. Syntax for Constants

const data_type variable_name = value;

2. Example

const double pi = 3.14159; // Declare a constant double variable

4.1.8 Putting It All Together


Let's combine the concepts of variables, data types, and auto in a complete example:

#include <iostream>

int main() {
// Declare and initialize variables
int age = 25;
double height = 5.9;
bool isStudent = true;

// Use auto to deduce types


auto weight = 68.5; // double
auto name = "Alice"; // const char*

// Print the values


76

std::cout << "Age: " << age << std::endl;


std::cout << "Height: " << height << std::endl;
std::cout << "Is Student: " << isStudent << std::endl;
std::cout << "Weight: " << weight << std::endl;
std::cout << "Name: " << name << std::endl;

return 0;
}

1. Explanation

(a) Variables:

• age, height, and isStudent are explicitly typed variables.


• weight and name are declared using auto.

(b) Output:

• The program prints the values of the variables to the console.

4.1.9 Summary
Variables and data types are fundamental concepts in C++ programming. By understanding how
to declare and initialize variables, use fundamental data types like int, double, and bool,
and leverage the auto keyword for type inference, you can write more efficient and readable
code. These concepts form the foundation for more advanced topics in Modern C++.
77

4.2 Input and Output (std::cin, std::cout)

4.2.1 Introduction to Input and Output in C++


Input and output (I/O) operations are essential for interacting with the user and displaying
information. In C++, the Standard Input/Output Library (<iostream>) provides the
std::cin and std::cout objects for handling input and output, respectively.

4.2.2 The std::cout Object


The std::cout object is used to output data to the console. It is part of the std namespace
and is an instance of the std::ostream class.

1. Syntax for std::cout

std::cout << expression;

• The << operator is called the insertion operator and is used to send data to the
output stream.

2. Example

#include <iostream>

int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}
78

• Output:

Hello, World!

3. Chaining Output

You can chain multiple << operators to output multiple items in a single statement:

std::cout << "The value of x is: " << x << std::endl;

4. std::endl

• The std::endl manipulator inserts a newline character and flushes the output
buffer.

• Example:

std::cout << "Line 1" << std::endl;


std::cout << "Line 2" << std::endl;

– Output:

Line 1
Line 2

4.2.3 The std::cin Object


The std::cin object is used to input data from the console. It is part of the std namespace
and is an instance of the std::istream class.
79

1. Syntax for std::cin

std::cin >> variable;

• The >> operator is called the extraction operator and is used to read data from the
input stream.

2. Example

#include <iostream>

int main() {
int age;
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "You are " << age << " years old." << std::endl;
return 0;
}

• Output (Example Interaction):

Enter your age: 25


You are 25 years old.

3. Chaining Input

You can chain multiple >> operators to input multiple values in a single statement:
80

int x, y;
std::cout << "Enter two numbers: ";
std::cin >> x >> y;
std::cout << "You entered: " << x << " and " << y << std::endl;

4.2.4 Handling Input Errors


When using std::cin, it's important to handle potential input errors, such as invalid data
types or unexpected input.

1. Checking for Valid Input


You can check if the input operation was successful using the std::cin.fail()
function:

#include <iostream>

int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;

if (std::cin.fail()) {
std::cerr << "Invalid input! Please enter a number." <<
,→ std::endl;
} else {
std::cout << "You entered: " << number << std::endl;
}

return 0;
}
81

2. Clearing the Error State


If an input error occurs, you can clear the error state and ignore invalid input using
std::cin.clear() and std::cin.ignore():

#include <iostream>
#include <limits>

int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;

if (std::cin.fail()) {
std::cin.clear(); // Clear the error state
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),
,→ '\n'); // Ignore invalid input
std::cerr << "Invalid input! Please enter a number." <<
,→ std::endl;
} else {
std::cout << "You entered: " << number << std::endl;
}

return 0;
}

4.2.5 Formatted Output

C++ provides several manipulators to format output, such as setting the precision of
floating-point numbers or aligning text.

(a) Setting Precision


82

Use std::setprecision to control the number of digits displayed for


floating-point numbers:

#include <iostream>
#include <iomanip> // For std::setprecision

int main() {
double pi = 3.141592653589793;
std::cout << "Pi to 3 decimal places: " <<
,→ std::setprecision(3) << pi << std::endl;
return 0;
}

• Output:

Pi to 3 decimal places: 3.14

(b) Aligning Text


Use std::setw to set the width of the output field:

#include <iostream>
#include <iomanip> // For std::setw

int main() {
std::cout << std::setw(10) << "Hello" << std::setw(10) <<
,→ "World" << std::endl;
return 0;
}

• Output:
83

Hello World

4.2.6 Putting It All Together

Let's combine the concepts of input and output in a complete example:

#include <iostream>
#include <iomanip>

int main() {
// Declare variables
std::string name;
int age;
double height;

// Input
std::cout << "Enter your name: ";
std::getline(std::cin, name); // Read a full line of text
std::cout << "Enter your age: ";
std::cin >> age;
std::cout << "Enter your height (in meters): ";
std::cin >> height;

// Output
std::cout << std::fixed << std::setprecision(2); // Set precision
,→ for floating-point numbers
std::cout << "\nName: " << name << std::endl;
std::cout << "Age: " << age << " years" << std::endl;
std::cout << "Height: " << height << " meters" << std::endl;
84

return 0;
}

(a) Explanation

i. Input:
• The program prompts the user to enter their name, age, and height.
• std::getline is used to read the full name, including spaces.
ii. Output:
• The program prints the user's name, age, and height with formatted
precision.

4.2.7 Summary

Input and output operations are fundamental to C++ programming. By mastering the use
of std::cin and std::cout, you can create interactive programs that communicate
effectively with users. Additionally, understanding how to handle input errors and format
output ensures that your programs are robust and user-friendly.
85

4.3 Operators (Arithmetic, Logical, Relational)

4.3.1 Introduction to Operators

Operators are symbols that perform operations on variables and values. In C++, operators
are categorized based on their functionality. The three main types of operators we will
cover in this section are:

(a) Arithmetic Operators: Perform mathematical operations.

(b) Relational Operators: Compare two values.

(c) Logical Operators: Combine or negate boolean expressions.

4.3.2 Arithmetic Operators

Arithmetic operators are used to perform basic mathematical operations such as addition,
subtraction, multiplication, and division.

(a) List of Arithmetic Operators

Operator Description Example


+ Addition a + b
- Subtraction a - b
* Multiplication a * b
/ Division a / b
% Modulus (remainder) a % b
++ Increment a++ or ++a
-- Decrement a-- or --a
86

(b) Examples

#include <iostream>

int main() {
int a = 10, b = 3;

std::cout << "a + b = " << (a + b) << std::endl; // 13


std::cout << "a - b = " << (a - b) << std::endl; // 7
std::cout << "a * b = " << (a * b) << std::endl; // 30
std::cout << "a / b = " << (a / b) << std::endl; // 3
,→ (integer division)
std::cout << "a % b = " << (a % b) << std::endl; // 1
,→ (remainder)

// Increment and Decrement


int c = 5;
std::cout << "c++ = " << c++ << std::endl; // 5
,→ (post-increment)
std::cout << "++c = " << ++c << std::endl; // 7
,→ (pre-increment)

int d = 8;
std::cout << "d-- = " << d-- << std::endl; // 8
,→ (post-decrement)
std::cout << "--d = " << --d << std::endl; // 6
,→ (pre-decrement)

return 0;
}

(c) Key Points


87

• Integer Division: When both operands are integers, the / operator performs
integer division, discarding the fractional part.
• Modulus Operator (%): Works only with integer operands and returns the
remainder of the division.
• Increment (++) and Decrement (--):
– Post-increment (a++): Returns the original value of a and then increments
it.
– Pre-increment (++a): Increments a and then returns the new value.

4.3.3 Relational Operators

Relational operators are used to compare two values or expressions. They return a boolean
value (true or false).

(a) List of Relational Operators

Operator Description Example


== Equal to a == b
!= Not equal to a != b
> Greater than a > b
< Less than a < b
>= Greater than or equal to a >= b
<= Less than or equal to a <= b

(b) Examples
88

#include <iostream>

int main() {
int a = 10, b = 20;

std::cout << "a == b: " << (a == b) << std::endl; // 0


,→ (false)
std::cout << "a != b: " << (a != b) << std::endl; // 1 (true)
std::cout << "a > b: " << (a > b) << std::endl; // 0
,→ (false)
std::cout << "a < b: " << (a < b) << std::endl; // 1 (true)
std::cout << "a >= b: " << (a >= b) << std::endl; // 0
,→ (false)
std::cout << "a <= b: " << (a <= b) << std::endl; // 1 (true)

return 0;
}

(c) Key Points

• Relational operators are often used in conditional statements (e.g., if, while)
to control the flow of a program.
• The result of a relational operation is a boolean value (true or false), which
is represented as 1 or 0 in C++.

4.3.4 Logical Operators

Logical operators are used to combine or negate boolean expressions. They are often used
in decision-making and looping constructs.

(a) List of Logical Operators


89

Operator Description Example


&& Logical AND a && b
|| Logical OR a || b
! Logical NOT !a

(b) Examples

#include <iostream>

int main() {
bool a = true, b = false;

std::cout << "a && b: " << (a && b) << std::endl; // 0


,→ (false)
std::cout << "a || b: " << (a || b) << std::endl; // 1 (true)
std::cout << "!a: " << (!a) << std::endl; // 0
,→ (false)
std::cout << "!b: " << (!b) << std::endl; // 1 (true)

return 0;
}

(c) Key Points

• Logical AND (&&): Returns true only if both operands are true.
• Logical OR (||): Returns true if at least one operand is true.
• Logical NOT (!): Negates the boolean value of the operand.
• Logical operators are often used in combination with relational operators to
form complex conditions.
90

4.3.5 Combining Operators

Operators can be combined to form more complex expressions. For example:

#include <iostream>

int main() {
int a = 10, b = 20, c = 30;

// Combining arithmetic and relational operators


bool result = (a + b) > (c - a); // (10 + 20) > (30 - 10) => 30 >
,→ 20 => true
std::cout << "Result: " << result << std::endl; // 1 (true)

// Combining logical and relational operators


bool condition = (a < b) && (b < c); // (10 < 20) && (20 < 30) =>
,→ true && true => true
std::cout << "Condition: " << condition << std::endl; // 1 (true)

return 0;
}

4.3.6 Operator Precedence and Associativity

When multiple operators are used in an expression, their evaluation order is determined by
operator precedence and associativity.

(a) Precedence Table


91

Precedence Operator Type Operators


Highest Postfix increment/decrement a++, a--
Prefix increment/decrement ++a, --a
Multiplicative *, /, %
Additive +, -
Relational <, >, <=, >=
Equality ==, !=
Logical AND &&
Logical OR ||
Lowest Assignment =, +=, -=, etc.

i. Example

int result = 5 + 3 * 2; // Multiplication has higher


,→ precedence than addition
std::cout << "Result: " << result << std::endl; // 11

4.3.7 Summary

Operators are fundamental to C++ programming, enabling you to perform arithmetic


calculations, compare values, and combine boolean expressions. By mastering arithmetic,
relational, and logical operators, you can write more expressive and efficient code.
Understanding operator precedence and associativity is also crucial for correctly
evaluating complex expressions.
Chapter 5

Control Flow

5.1 if, else, switch

5.1.1 Introduction to Control Flow

Control flow statements allow you to control the execution of your program based on
certain conditions. In C++, the primary conditional statements are:

(a) if and else: Used to execute code blocks based on boolean conditions.

(b) switch: Used to select one of many code blocks to execute based on the value of a
variable.

5.1.2 The if Statement

The if statement is used to execute a block of code if a specified condition is true.

92
93

(a) Syntax

if (condition) {
// Code to execute if condition is true
}

(b) Example

#include <iostream>

int main() {
int age = 20;

if (age >= 18) {


std::cout << "You are an adult." << std::endl;
}

return 0;
}

• Output:

You are an adult.

(c) Key Points

• The condition must evaluate to a boolean value (true or false).


• If the condition is true, the code inside the if block is executed.
94

5.1.3 Statement

The if-else statement allows you to execute one block of code if a condition is true
and another block if the condition is false.

(a) Syntax

if (condition) {
// Code to execute if condition is true
} else {
// Code to execute if condition is false
}

(b) Example

#include <iostream>

int main() {
int age = 15;

if (age >= 18) {


std::cout << "You are an adult." << std::endl;
} else {
std::cout << "You are a minor." << std::endl;
}

return 0;
}

• Output:
95

You are a minor.

(c) Key Points

• The else block is optional and is executed only if the if condition is false.

5.1.4 The if-else if-else Statement

The if-else if-else statement allows you to test multiple conditions and execute
different code blocks based on which condition is true.

(a) Syntax

if (condition1) {
// Code to execute if condition1 is true
} else if (condition2) {
// Code to execute if condition2 is true
} else {
// Code to execute if all conditions are false
}

(b) Example

#include <iostream>

int main() {
int score = 85;

if (score >= 90) {


std::cout << "Grade: A" << std::endl;
} else if (score >= 80) {
96

std::cout << "Grade: B" << std::endl;


} else if (score >= 70) {
std::cout << "Grade: C" << std::endl;
} else {
std::cout << "Grade: F" << std::endl;
}

return 0;
}

• Output:

Grade: B

(c) Key Points

• You can have multiple else if blocks to test additional conditions.


• The else block is optional and is executed only if all previous conditions are
false.

5.1.5 The switch Statement

The switch statement allows you to select one of many code blocks to execute based on
the value of a variable or expression.

(a) Syntax

switch (expression) {
case value1:
// Code to execute if expression == value1
97

break;
case value2:
// Code to execute if expression == value2
break;
// More cases...
default:
// Code to execute if expression does not match any case
}

(b) Example

#include <iostream>

int main() {
int day = 3;

switch (day) {
case 1:
std::cout << "Monday" << std::endl;
break;
case 2:
std::cout << "Tuesday" << std::endl;
break;
case 3:
std::cout << "Wednesday" << std::endl;
break;
case 4:
std::cout << "Thursday" << std::endl;
break;
case 5:
std::cout << "Friday" << std::endl;
break;
98

case 6:
std::cout << "Saturday" << std::endl;
break;
case 7:
std::cout << "Sunday" << std::endl;
break;
default:
std::cout << "Invalid day" << std::endl;
}

return 0;
}

• Output:

Wednesday

(c) Key Points

• The expression must evaluate to an integral or enumeration type (e.g., int,


char).
• Each case label must be a constant expression.
• The break statement is used to exit the switch block. If omitted, execution
will ”fall through” to the next case.
• The default case is optional and is executed if no other case matches the
expression.

5.1.6 Nested Conditional Statements

Conditional statements can be nested within each other to handle more complex logic.
99

(a) Example

#include <iostream>

int main() {
int age = 20;
bool isStudent = true;

if (age >= 18) {


if (isStudent) {
std::cout << "You are an adult student." <<
,→ std::endl;
} else {
std::cout << "You are an adult." << std::endl;
}
} else {
std::cout << "You are a minor." << std::endl;
}

return 0;
}

• Output:

You are an adult student.

(b) Key Points

• Nested if statements allow you to test additional conditions within an if or


else block.
• Be cautious with deeply nested structures, as they can reduce code readability.
100

5.1.7 Best Practices for Conditional Statements

(a) Use Braces {}: Always use braces for if, else, and switch blocks, even if they
contain only one statement. This improves readability and avoids bugs.
(b) Avoid Deep Nesting: Deeply nested if statements can make code hard to read.
Consider refactoring or using functions to simplify logic.
(c) Use switch for Multiple Conditions: When comparing a single variable against
multiple values, prefer switch over multiple if-else if statements for better
readability.
(d) Default Case in switch: Always include a default case in switch statements
to handle unexpected values.

5.1.8 Summary

Conditional statements (if, else, and switch) are essential tools for controlling the
flow of your C++ programs. They allow you to execute different blocks of code based on
specific conditions, making your programs more dynamic and flexible. By mastering these
constructs and following best practices, you can write clean, efficient, and maintainable
code.
101

5.2 Loops (for, while, do-while)

5.2.1 Introduction to Loops

Loops are control flow statements that allow you to execute a block of code repeatedly
based on a condition. They are essential for tasks that require repetitive operations, such
as iterating over arrays, processing data, or implementing algorithms. In C++, there are
three primary types of loops:

(a) for Loop: Used when the number of iterations is known or can be determined.

(b) while Loop: Used when the number of iterations is not known in advance, and the
loop continues as long as a condition is true.

(c) do-while Loop: Similar to the while loop, but the condition is evaluated after
the loop body, ensuring that the loop executes at least once.

5.2.2 The for Loop

The for loop is used when you know how many times you want to execute a block of
code. It consists of three parts: initialization, condition, and update.

(a) Syntax

for (initialization; condition; update) {


// Code to execute
}

(b) Example
102

#include <iostream>

int main() {
for (int i = 0; i < 5; ++i) {
std::cout << "Iteration: " << i << std::endl;
}

return 0;
}

• Output:

Iteration: 0
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4

(c) Key Points

• Initialization: Executed once at the beginning of the loop. Typically used to


initialize a loop counter.
• Condition: Evaluated before each iteration. If true, the loop body is executed.
• Update: Executed after each iteration. Typically used to update the loop
counter.
• The loop terminates when the condition becomes false.

(d) Range-Based for Loop (C++11)


C++11 introduced the range-based for loop, which simplifies iterating over
collections like arrays, vectors, and other containers.
103

Syntax

for (element_declaration : collection) {


// Code to execute
}

Example

#include <iostream>
#include <vector>

int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};

for (int num : numbers) {


std::cout << num << " ";
}

return 0;
}

• Output:

1 2 3 4 5

5.2.3 The while Loop

The while loop is used when the number of iterations is not known in advance, and the
loop continues as long as a condition is true.
104

(a) Syntax

while (condition) {
// Code to execute
}

(b) Example

#include <iostream>

int main() {
int count = 0;

while (count < 5) {


std::cout << "Count: " << count << std::endl;
++count;
}

return 0;
}

• Output:

Count: 0
Count: 1
Count: 2
Count: 3
Count: 4

(c) Key Points


• The loop continues as long as the condition is true.
• Be cautious of infinite loops, where the condition never becomes false.
105

5.2.4 The do-while Loop

The do-while loop is similar to the while loop, but the condition is evaluated after the
loop body. This ensures that the loop executes at least once.

(a) Syntax

do {
// Code to execute
} while (condition);

(b) Example

#include <iostream>

int main() {
int count = 0;

do {
std::cout << "Count: " << count << std::endl;
++count;
} while (count < 5);

return 0;
}

• Output:

Count: 0
Count: 1
Count: 2
106

Count: 3
Count: 4

(c) Key Points


• The loop body is executed at least once, even if the condition is false initially.
• Useful for scenarios where you want to ensure the loop body runs before
checking the condition.

5.2.5 Loop Control Statements

C++ provides control statements to manage the flow of loops:

(a) break: Exits the loop immediately.


(b) continue: Skips the rest of the loop body and proceeds to the next iteration.
(c) goto: Jumps to a labeled statement (rarely used and generally discouraged).

(a) Example of break

#include <iostream>

int main() {
for (int i = 0; i < 10; ++i) {
if (i == 5) {
break; // Exit the loop when i == 5
}
std::cout << i << " ";
}

return 0;
}
107

• Output:

0 1 2 3 4

(b) Example of continue

#include <iostream>

int main() {
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0) {
continue; // Skip even numbers
}
std::cout << i << " ";
}

return 0;
}

• Output:

1 3 5 7 9

5.2.6 Nested Loops

Loops can be nested within each other to handle more complex tasks, such as working
with multi-dimensional arrays.

(a) Example
108

#include <iostream>

int main() {
for (int i = 1; i <= 3; ++i) {
for (int j = 1; j <= 3; ++j) {
std::cout << "(" << i << ", " << j << ") ";
}
std::cout << std::endl;
}

return 0;
}

• Output:

(1, 1) (1, 2) (1, 3)


(2, 1) (2, 2) (2, 3)
(3, 1) (3, 2) (3, 3)

(b) Key Points


• Nested loops are useful for working with multi-dimensional data structures.
• Be cautious with deeply nested loops, as they can reduce code readability and
performance.

5.2.7 Best Practices for Loops

(a) Use the Right Loop: Choose the loop type (for, while, do-while) based on
the problem requirements.
(b) Avoid Infinite Loops: Ensure that the loop condition will eventually become
false.
109

(c) Minimize Loop Nesting: Deeply nested loops can be hard to read and debug.
Consider refactoring or using functions to simplify logic.
(d) Use Range-Based for Loops: Prefer range-based for loops when iterating over
collections.
(e) Limit Scope of Loop Variables: Declare loop variables (e.g., i) within the loop to
limit their scope.

5.2.8 Summary

Loops (for, while, do-while) are powerful tools for controlling repetitive tasks in
C++ programs. By mastering these constructs and following best practices, you can write
efficient, readable, and maintainable code. Whether you're iterating over collections,
processing data, or implementing algorithms, loops are an essential part of your
programming toolkit.
Chapter 6

Functions

6.1 Defining and Calling Functions

6.1.1 Introduction to Functions

A function is a reusable block of code that performs a specific task. Functions are
essential for organizing code, improving readability, and promoting code reuse. In C++,
functions can take input parameters, perform operations, and return results.

6.1.2 Defining a Function

To define a function in C++, you need to specify its return type, name, parameters, and
body.

(a) Syntax

110
111

return_type function_name(parameter_list) {
// Function body
// Code to execute
return value; // Optional, depending on return_type
}

• return type: The type of value the function returns (e.g., int, double,
void).
• function name: The name of the function, which should be descriptive and
follow naming conventions.
• parameter list: A comma-separated list of parameters (inputs) the
function accepts. Each parameter has a type and a name.
• function body: The block of code that defines what the function does.
• return statement: Used to return a value to the caller. If the return type is
void, the return statement is optional.
(b) Example

#include <iostream>

// Function definition
int add(int a, int b) {
return a + b;
}

6.1.3 Calling a Function

Once a function is defined, you can call it from other parts of your program by using its
name and providing the required arguments.
112

(a) Syntax

function_name(arguments);

• function name: The name of the function to call.


• arguments: The actual values passed to the function's parameters.

(b) Example

#include <iostream>

// Function definition
int add(int a, int b) {
return a + b;
}

int main() {
int result = add(3, 5); // Function call
std::cout << "Result: " << result << std::endl; // Output: 8
return 0;
}

6.1.4 Function Parameters and Arguments

• Parameters: Variables declared in the function definition.

• Arguments: Actual values passed to the function when it is called.

(a) Example
113

#include <iostream>

// Function with parameters


void printMessage(std::string message) {
std::cout << message << std::endl;
}

int main() {
printMessage("Hello, World!"); // Function call with argument
return 0;
}

• Output:

Hello, World!

6.1.5 Return Values

Functions can return a value to the caller using the return statement. The return type
must match the function's declared return type.

(a) Example

#include <iostream>

// Function with return value


double multiply(double a, double b) {
return a * b;
}
114

int main() {
double result = multiply(2.5, 4.0); // Function call
std::cout << "Result: " << result << std::endl; // Output:
,→ 10.0
return 0;
}

(b) void Functions


Functions that do not return a value should have a return type of void. The
return statement is optional in such functions.
Example

#include <iostream>

// void function
void greet() {
std::cout << "Hello, User!" << std::endl;
}

int main() {
greet(); // Function call
return 0;
}

• Output:

Hello, User!
115

6.1.6 Function Prototypes

A function prototype declares a function's name, return type, and parameters without
defining its body. It allows you to call a function before defining it.

(a) Syntax

return_type function_name(parameter_list);

(b) Example

#include <iostream>

// Function prototype
int add(int a, int b);

int main() {
int result = add(3, 5); // Function call
std::cout << "Result: " << result << std::endl; // Output: 8
return 0;
}

// Function definition
int add(int a, int b) {
return a + b;
}

6.1.7 Default Arguments

C++ allows you to specify default arguments for function parameters. If an argument is
not provided when the function is called, the default value is used.
116

(a) Syntax

return_type function_name(parameter_type parameter_name =


,→ default_value);

(b) Example

#include <iostream>

// Function with default argument


void printMessage(std::string message = "Hello, World!") {
std::cout << message << std::endl;
}

int main() {
printMessage(); // Uses default argument
printMessage("Goodbye, World!"); // Overrides default
,→ argument
return 0;
}

• Output:

Hello, World!
Goodbye, World!

6.1.8 Function Overloading

C++ supports function overloading, which allows you to define multiple functions with
the same name but different parameter lists.
117

(a) Example

#include <iostream>

// Overloaded functions
int add(int a, int b) {
return a + b;
}

double add(double a, double b) {


return a + b;
}

int main() {
std::cout << "Integer addition: " << add(3, 5) << std::endl;
,→ // Output: 8
std::cout << "Double addition: " << add(2.5, 4.0) <<
,→ std::endl; // Output: 6.5
return 0;
}

6.1.9 Inline Functions

The inline keyword suggests that the compiler replace the function call with the
function's body to reduce overhead. This is useful for small, frequently called functions.

(a) Syntax

inline return_type function_name(parameter_list) {


// Function body
}
118

(b) Example

#include <iostream>

// Inline function
inline int square(int x) {
return x * x;
}

int main() {
std::cout << "Square of 5: " << square(5) << std::endl; //
,→ Output: 25
return 0;
}

6.1.10 Best Practices for Functions

(a) Use Descriptive Names: Choose meaningful names for functions and parameters.
(b) Keep Functions Small: Functions should perform a single, well-defined task.
(c) Avoid Global Variables: Prefer passing data to functions via parameters.
(d) Use Default Arguments Sparingly: Default arguments can make code harder to
understand if overused.
(e) Document Functions: Use comments to describe the purpose, parameters, and
return value of functions.

6.1.11 Summary

Functions are a cornerstone of C++ programming, enabling code reuse, modularity, and
readability. By mastering the concepts of defining and calling functions, using parameters
119

and return values, and leveraging advanced features like function overloading and default
arguments, you can write clean, efficient, and maintainable code.
120

6.2 Function Parameters and Return Values

6.2.1 Introduction to Function Parameters and Return Values

Function parameters and return values are fundamental to how functions interact with the
rest of your program. Parameters allow you to pass data into a function, while return
values allow a function to send data back to the caller. Understanding how to use
parameters and return values effectively is key to writing modular and reusable code.

6.2.2 Function Parameters

Function parameters are variables declared in the function signature that act as
placeholders for the values (arguments) passed to the function when it is called.

(a) Syntax

return_type function_name(parameter_type parameter_name) {


// Function body
}

(b) Example

#include <iostream>

// Function with parameters


void printMessage(std::string message) {
std::cout << message << std::endl;
}
121

int main() {
printMessage("Hello, World!"); // Function call with argument
return 0;
}

• Output:

Hello, World!

(c) Multiple Parameters


Functions can have multiple parameters, separated by commas.
Example

#include <iostream>

// Function with multiple parameters


int add(int a, int b) {
return a + b;
}

int main() {
int result = add(3, 5); // Function call
std::cout << "Result: " << result << std::endl; // Output: 8
return 0;
}

6.2.3 Passing Arguments to Functions

When calling a function, you pass arguments that correspond to the function's parameters.
The arguments can be literals, variables, or expressions.
122

(a) Example

#include <iostream>

// Function with parameters


void printSum(int a, int b) {
std::cout << "Sum: " << (a + b) << std::endl;
}

int main() {
int x = 10, y = 20;
printSum(x, y); // Pass variables as arguments
printSum(5, 15); // Pass literals as arguments
return 0;
}

• Output:

Sum: 30
Sum: 20

6.2.4 Return Values

Functions can return a value to the caller using the return statement. The return type
must match the function's declared return type.

(a) Syntax

return_type function_name(parameters) {
// Function body
123

return value; // Return a value


}

(b) Example

#include <iostream>

// Function with return value


double multiply(double a, double b) {
return a * b;
}

int main() {
double result = multiply(2.5, 4.0); // Function call
std::cout << "Result: " << result << std::endl; // Output:
,→ 10.0
return 0;
}

(c) void Functions


Functions that do not return a value should have a return type of void. The
return statement is optional in such functions.
Example

#include <iostream>

// void function
void greet() {
std::cout << "Hello, User!" << std::endl;
}
124

int main() {
greet(); // Function call
return 0;
}

• Output:

Hello, User!

6.2.5 Passing Parameters by Value vs. by Reference

C++ allows you to pass parameters by value or by reference, which affects how the
function interacts with the arguments.

(a) Pass by Value

• A copy of the argument is passed to the function.


• Changes to the parameter inside the function do not affect the original argument.

Example

#include <iostream>

// Pass by value
void increment(int x) {
++x; // Changes the local copy of x
}

int main() {
int a = 5;
125

increment(a);
std::cout << "a: " << a << std::endl; // Output: 5
,→ (unchanged)
return 0;
}

(b) Pass by Reference

• A reference to the argument is passed to the function.


• Changes to the parameter inside the function affect the original argument.

Example

#include <iostream>

// Pass by reference
void increment(int& x) {
++x; // Changes the original argument
}

int main() {
int a = 5;
increment(a);
std::cout << "a: " << a << std::endl; // Output: 6 (changed)
return 0;
}

6.2.6 Default Arguments

C++ allows you to specify default arguments for function parameters. If an argument is
not provided when the function is called, the default value is used.
126

(a) Syntax

return_type function_name(parameter_type parameter_name =


,→ default_value);

(b) Example

#include <iostream>

// Function with default argument


void printMessage(std::string message = "Hello, World!") {
std::cout << message << std::endl;
}

int main() {
printMessage(); // Uses default argument
printMessage("Goodbye, World!"); // Overrides default
,→ argument
return 0;
}

• Output:

Hello, World!
Goodbye, World!

6.2.7 Returning Multiple Values

C++ functions can return only one value directly. However, you can return multiple values
using:
127

(a) Structures or Classes: Define a struct or class to hold multiple values.


(b) References or Pointers: Use reference or pointer parameters to return additional
values.

(a) Example Using a Struct

#include <iostream>

// Struct to hold multiple values


struct Result {
int sum;
int product;
};

// Function returning a struct


Result compute(int a, int b) {
return {a + b, a * b}; // Return a struct
}

int main() {
Result result = compute(3, 4);
std::cout << "Sum: " << result.sum << ", Product: " <<
,→ result.product << std::endl;
return 0;
}

• Output:

Sum: 7, Product: 12

(b) Example Using References


128

#include <iostream>

// Function returning multiple values via references


void compute(int a, int b, int& sum, int& product) {
sum = a + b;
product = a * b;
}

int main() {
int sum, product;
compute(3, 4, sum, product);
std::cout << "Sum: " << sum << ", Product: " << product <<
,→ std::endl;
return 0;
}

• Output:

Sum: 7, Product: 12

6.2.8 Best Practices for Parameters and Return Values

(a) Use Descriptive Names: Choose meaningful names for parameters and return
values.

(b) Prefer Pass by Reference for Large Objects: Avoid copying large objects by
passing them by reference.

(c) Use const for Read-Only Parameters: Mark parameters as const if they are
not modified inside the function.
129

(d) Avoid Overusing Default Arguments: Default arguments can make code harder to
understand if overused.
(e) Document Parameters and Return Values: Use comments to describe the purpose
and behavior of parameters and return values.

6.2.9 Summary

Function parameters and return values are essential for creating flexible and reusable
functions in C++. By understanding how to pass arguments, return values, and use
advanced features like default arguments and pass-by-reference, you can write efficient
and maintainable code. These concepts form the foundation for more advanced topics like
function overloading, templates, and lambda expressions.
130

6.3 Inline Functions and constexpr

6.3.1 Introduction to Inline Functions and constexpr

C++ provides two powerful features to optimize and enhance the functionality of
functions: inline functions and constexpr functions. These features allow you to
improve performance, reduce overhead, and enable compile-time computations.

6.3.2 Inline Functions

The inline keyword is a suggestion to the compiler to replace the function call with the
actual code of the function. This can reduce the overhead of function calls, especially for
small, frequently called functions.

(a) Syntax

inline return_type function_name(parameters) {


// Function body
}

(b) Example

#include <iostream>

// Inline function
inline int square(int x) {
return x * x;
}
131

int main() {
int result = square(5); // Function call
std::cout << "Square of 5: " << result << std::endl; //
,→ Output: 25
return 0;
}

(c) Key Points

• Performance: Inline functions can improve performance by eliminating the


overhead of function calls.
• Compiler Discretion: The inline keyword is a suggestion, and the compiler
may choose to ignore it.
• Use Case: Best suited for small, frequently called functions.

(d) Best Practices

• Use inline for small functions that are called frequently.


• Avoid using inline for large functions, as it can increase the size of the
binary.

6.3.3 constexpr Functions

The constexpr keyword indicates that a function can be evaluated at compile time if its
arguments are constant expressions. This allows for compile-time computations, which
can improve performance and enable certain optimizations.

(a) Syntax
132

constexpr return_type function_name(parameters) {


// Function body
}

(b) Example

#include <iostream>

// constexpr function
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}

int main() {
constexpr int result = factorial(5); // Compile-time
,→ computation
std::cout << "Factorial of 5: " << result << std::endl; //
,→ Output: 120
return 0;
}

(c) Key Points


• Compile-Time Evaluation: constexpr functions can be evaluated at
compile time if all arguments are constant expressions.
• Performance: Compile-time evaluation can reduce runtime overhead.
• Use Case: Ideal for functions that perform computations on constant values.
(d) Best Practices
• Use constexpr for functions that can be evaluated at compile time.
• Ensure that all parameters and operations within the function are valid in a
constant expression context.
133

6.3.4 Combining inline and constexpr

You can combine inline and constexpr to create functions that are both inlined and
evaluated at compile time when possible.

(a) Example

#include <iostream>

// Inline constexpr function


inline constexpr int square(int x) {
return x * x;
}

int main() {
constexpr int result = square(5); // Compile-time computation
std::cout << "Square of 5: " << result << std::endl; //
,→ Output: 25
return 0;
}

(b) Key Points

• Combining inline and constexpr can provide both performance benefits


and compile-time evaluation.
• The function can be inlined for runtime calls and evaluated at compile time for
constant expressions.

(c) Differences Between inline and constexpr


134

Feature inline constexpr


Purpose Reduce function call overhead Enable compile-time evaluation
Evaluation Time Runtime Compile-time (if arguments are
const)
Use Case Small, frequently called functions Functions with constant
expressions
Compiler Discretion Suggestion (compiler may Mandatory for compile-time
ignore) evaluation

6.3.5 Practical Examples

(a) Inline Function for Vector Magnitude

#include <iostream>
#include <cmath>

// Inline function for vector magnitude


inline double magnitude(double x, double y, double z) {
return std::sqrt(x * x + y * y + z * z);
}

int main() {
double mag = magnitude(3.0, 4.0, 5.0); // Function call
std::cout << "Magnitude: " << mag << std::endl; // Output:
,→ 7.07107
return 0;
}

(b) constexpr Function for Compile-Time Factorial


135

#include <iostream>

// constexpr function for factorial


constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}

int main() {
constexpr int result = factorial(5); // Compile-time
,→ computation
std::cout << "Factorial of 5: " << result << std::endl; //
,→ Output: 120
return 0;
}

6.3.6 Best Practices

(a) Use inline for Small Functions: Apply inline to small, frequently called
functions to reduce call overhead.

(b) Use constexpr for Compile-Time Computations: Use constexpr for


functions that can be evaluated at compile time to improve performance.

(c) Combine inline and constexpr: When appropriate, combine both keywords
to leverage their benefits.

(d) Avoid Overuse: Do not overuse inline or constexpr for large or complex
functions, as it can lead to code bloat or compilation errors.
136

6.3.7 Summary

Inline functions and constexpr functions are powerful tools in C++ for optimizing
performance and enabling compile-time computations. By understanding their syntax, use
cases, and best practices, you can write efficient and maintainable code that takes full
advantage of Modern C++ features.
Chapter 7

Practical Examples

7.1 Simple Programs to Reinforce Concepts

7.1.1 Introduction

In this section, we will create two simple programs to reinforce the concepts of variables,
control flow, functions, and input/output in C++. These programs are:

(a) Calculator: A basic calculator that performs addition, subtraction, multiplication,


and division.

(b) Number Guessing Game: A game where the user guesses a randomly generated
number.

These programs will help you practice and solidify your understanding of Modern C++.

137
138

7.1.2 Calculator Program

The calculator program will take two numbers and an operation (+, -, *, /) as input from
the user and display the result.

(a) Step-by-Step Explanation


i. Input: Prompt the user to enter two numbers and an operation.
ii. Processing: Perform the selected operation on the two numbers.
iii. Output: Display the result of the operation.
(b) Code Example

#include <iostream>

int main() {
double num1, num2;
char operation;

// Input
std::cout << "Enter first number: ";
std::cin >> num1;

std::cout << "Enter second number: ";


std::cin >> num2;

std::cout << "Enter operation (+, -, *, /): ";


std::cin >> operation;

// Processing and Output


switch (operation) {
case '+':
std::cout << "Result: " << (num1 + num2) <<
,→ std::endl;
139

break;
case '-':
std::cout << "Result: " << (num1 - num2) <<
,→ std::endl;
break;
case '*':
std::cout << "Result: " << (num1 * num2) <<
,→ std::endl;
break;
case '/':
if (num2 != 0) {
std::cout << "Result: " << (num1 / num2) <<
,→ std::endl;
} else {
std::cout << "Error: Division by zero!" <<
,→ std::endl;
}
break;
default:
std::cout << "Invalid operation!" << std::endl;
}

return 0;
}

(c) Key Concepts Reinforced

• Variables: num1, num2, and operation store user input.


• Input/Output: std::cin and std::cout are used for user interaction.
• Control Flow: The switch statement handles different operations.
• Error Handling: Checks for division by zero.
140

7.1.3 Number Guessing Game

The number guessing game will generate a random number between 1 and 100, and the
user will guess the number. The program will provide feedback (too high, too low) until
the user guesses correctly.

(a) Step-by-Step Explanation


i. Generate Random Number: Use the <cstdlib> and <ctime> libraries
to generate a random number.
ii. Input: Prompt the user to enter a guess.
iii. Processing: Compare the guess to the random number and provide feedback.
iv. Output: Display the result of each guess and the number of attempts.
(b) Code Example

#include <iostream>
#include <cstdlib> // For rand() and srand()
#include <ctime> // For time()

int main() {
// Seed the random number generator
std::srand(static_cast<unsigned int>(std::time(0)));

// Generate a random number between 1 and 100


int randomNumber = std::rand() % 100 + 1;
int guess = 0;
int attempts = 0;

std::cout << "Welcome to the Number Guessing Game!" <<


,→ std::endl;
std::cout << "I have chosen a number between 1 and 100. Can
,→ you guess it?" << std::endl;
141

do {
// Input
std::cout << "Enter your guess: ";
std::cin >> guess;
++attempts;

// Processing and Output


if (guess < randomNumber) {
std::cout << "Too low! Try again." << std::endl;
} else if (guess > randomNumber) {
std::cout << "Too high! Try again." << std::endl;
} else {
std::cout << "Congratulations! You guessed the number
,→ in " << attempts << " attempts." << std::endl;
}
} while (guess != randomNumber);

return 0;
}

(c) Key Concepts Reinforced

• Random Number Generation: Use of std::rand() and


std::srand().
• Loops: The do-while loop ensures the game continues until the user guesses
correctly.
• Conditional Statements: if-else statements provide feedback based on the
user's guess.
• Variables: randomNumber, guess, and attempts store game state.
142

7.1.4 Best Practices

(a) Modularize Code: Break the program into functions for better readability and
reusability.
(b) Error Handling: Validate user input to handle invalid entries gracefully.
(c) Comments: Use comments to explain the purpose of each section of code.
(d) Testing: Test the program with different inputs to ensure it works as expected.

7.1.5 Summary

The calculator and number guessing game programs are excellent examples to reinforce
fundamental C++ concepts. By writing and understanding these programs, you will gain
confidence in using variables, control flow, functions, and input/output operations. These
skills form the foundation for more advanced programming tasks in Modern C++.
Chapter 8

Debugging and version control

8.1 Debugging Basics (Using GDB or IDE Debuggers)

8.1.1 Introduction to Debugging

Debugging is the process of identifying and resolving errors (bugs) in your code. Effective
debugging is crucial for developing reliable and efficient software. In C++, you can use
tools like GDB (a command-line debugger) or IDE Debuggers (e.g., Visual Studio,
CLion, VS Code) to debug your programs.

8.1.2 Debugging with GDB

GDB (GNU Debugger) is a powerful command-line tool for debugging C++ programs. It
allows you to inspect the state of your program, set breakpoints, step through code, and
analyze crashes.

143
144

1.2.1 Compiling for Debugging To use GDB, you must compile your program with
debugging information. Use the -g flag with your compiler:

g++ -g -o my_program my_program.cpp

1.2.2 Starting GDB Run GDB with your compiled program:

bash

Copy

gdb ./my_program

1.2.3 Basic GDB Commands Here are some essential GDB commands:

Command Description
break <line> Set a breakpoint at a specific line number.
run Start the program.
next Execute the next line of code (step over).
step Execute the next line of code (step into).
print <variable> Print the value of a variable.
backtrace Display the call stack.
continue Continue execution until the next breakpoint.
quit Exit GDB.

1.2.4 Example Debugging Session Consider the following program


(my program.cpp):
145

#include <iostream>

int main() {
int x = 10;
int y = 0;
int z = x / y; // Division by zero
std::cout << "z: " << z << std::endl;
return 0;
}

(a) Compile with Debugging Information:

g++ -g -o my_program my_program.cpp

(b) Start GDB:

gdb ./my_program

(c) Set a Breakpoint:

break 6

(d) Run the Program:

run

(e) Inspect Variables:


146

print x
print y

(f) Step Through Code:

next

(g) Analyze the Crash:

• GDB will stop at the division by zero error.


• Use backtrace to inspect the call stack.

(h) Quit GDB:

quit

8.1.3 Debugging with IDE Debuggers

Modern IDEs like Visual Studio, CLion, and VS Code provide integrated debugging
tools with a graphical interface. These tools simplify debugging by allowing you to set
breakpoints, inspect variables, and step through code visually.

1.3.1 Visual Studio Debugger

(a) Set Breakpoints:

• Click in the left margin next to the line of code where you want to set a
breakpoint.

(b) Start Debugging:


147

• Press F5 or click Debug > Start Debugging.

(c) Inspect Variables:

• Hover over variables to see their values, or use the Watch window.

(d) Step Through Code:

• Use F10 (Step Over) or F11 (Step Into) to execute code line by line.

(e) View Call Stack:

• Use the Call Stack window to inspect the sequence of function calls.

1.3.2 CLion Debugger

(a) Set Breakpoints:

• Click in the left margin next to the line of code where you want to set a
breakpoint.

(b) Start Debugging:

• Press Shift + F9 or click Run > Debug.

(c) Inspect Variables:

• Use the Variables window to see the values of variables.

(d) Step Through Code:

• Use F8 (Step Over) or F7 (Step Into) to execute code line by line.

(e) View Call Stack:

• Use the Debugger tab to inspect the call stack.


148

1.3.3 VS Code Debugger

(a) Set Breakpoints:

• Click in the left margin next to the line of code where you want to set a
breakpoint.

(b) Start Debugging:

• Press F5 or click Run > Start Debugging.

(c) Inspect Variables:

• Use the Variables pane to see the values of variables.

(d) Step Through Code:

• Use F10 (Step Over) or F11 (Step Into) to execute code line by line.

(e) View Call Stack:

• Use the Call Stack pane to inspect the sequence of function calls.

8.1.4 Common Debugging Techniques

(a) Set Breakpoints:

• Breakpoints allow you to pause execution at specific lines of code.


• Use breakpoints to inspect the state of your program at critical points.

(b) Step Through Code:

• Use Step Over to execute the next line of code without entering functions.
• Use Step Into to enter and debug functions.

(c) Inspect Variables:

• Check the values of variables to ensure they are as expected.


149

• Use Watch windows to monitor specific variables.

(d) Analyze Call Stack:

• The call stack shows the sequence of function calls leading to the current point
of execution.
• Use the call stack to trace the origin of errors.

(e) Handle Crashes:

• Use debugging tools to identify the cause of crashes (e.g., segmentation faults).
• Inspect the call stack and variable values at the point of failure.

8.1.5 Best Practices for Debugging

(a) Reproduce the Issue:

• Ensure you can consistently reproduce the bug before debugging.

(b) Start Small:

• Isolate the problem by testing small sections of code.

(c) Use Logging:

• Add logging statements to track the flow of execution and variable values.

(d) Check Assumptions:

• Verify that your assumptions about the program's behavior are correct.

(e) Take Notes:

• Document your debugging process, including hypotheses and findings.


150

8.1.6 Summary

Debugging is an essential skill for any programmer. By mastering tools like GDB and
IDE Debuggers, you can efficiently identify and resolve errors in your C++ programs.
Whether you prefer command-line tools or graphical interfaces, understanding debugging
techniques will help you develop more reliable and efficient software.

8.2 Introduction to Version Control (Git)

8.2.1 Introduction to Version Control

Version control is a system that records changes to files over time, allowing you to track
modifications, revert to previous states, and collaborate with others. Git is the most widely
used version control system, known for its speed, flexibility, and distributed nature.

8.2.2 Why Use Version Control?

(a) Track Changes: Keep a history of all changes made to your code.
(b) Collaborate: Work with others on the same project without conflicts.
(c) Revert Mistakes: Easily revert to a previous version if something goes wrong.
(d) Branching and Merging: Create separate branches for new features or experiments
and merge them back into the main codebase.
(e) Backup: Maintain a backup of your code in a remote repository.

8.2.3 Installing Git

Before using Git, you need to install it on your system.


151

(a) On Linux

sudo apt update


sudo apt install git

(b) On macOS

brew install git

(c) On Windows
Download and install Git from the official website.

8.2.4 Basic Git Concepts

(a) Repository (Repo): A directory where Git tracks changes to files.

(b) Commit: A snapshot of the repository at a specific point in time.

(c) Branch: A separate line of development. The default branch is usually called main
or master.

(d) Clone: Create a copy of a remote repository on your local machine.

(e) Push: Upload local changes to a remote repository.

(f) Pull: Download changes from a remote repository to your local machine.

(g) Merge: Combine changes from different branches.

8.2.5 Basic Git Commands

Here are some essential Git commands:


152

Command Description
git init Initialize a new Git repository.
git clone <url> Clone a remote repository to your local machine.
git status Show the status of the working directory.
git add <file> Stage changes for the next commit.
git commit -m "msg" Commit staged changes with a message.
git push Push local commits to a remote repository.
git pull Pull changes from a remote repository.
git branch List all branches in the repository.
git checkout Switch to a different branch.
<branch>
git merge <branch> Merge changes from another branch.

8.2.6 Setting Up a Git Repository

(a) Initialize a New Repository

i. Create a new directory for your project:

mkdir my_project
cd my_project

ii. Initialize a Git repository:

git init

(b) Clone an Existing Repository


To clone a remote repository:
153

git clone https://github.com/username/repository.git

8.2.7 Basic Git Workflow

(a) Make Changes:

• Edit files in your project.

(b) Stage Changes:

• Use git add to stage changes for the next commit.

git add <file>

(c) Commit Changes:

• Use git commit to create a snapshot of the staged changes.

git commit -m "Your commit message"

(d) Push Changes:

• Use git push to upload your commits to a remote repository.

git push origin main

(e) Pull Changes:

• Use git pull to download changes from a remote repository.


154

git pull origin main

8.2.8 Branching and Merging

Branching allows you to work on new features or experiments without affecting the main
codebase.

(a) Create a New Branch

git branch new_feature

(b) Switch to a Branch

git checkout new_feature

(c) Merge a Branch

i. Switch to the branch you want to merge into (e.g., main):

git checkout main

ii. Merge the feature branch:

git merge new_feature

8.2.9 Remote Repositories

Remote repositories allow you to collaborate with others and back up your code.
155

(a) Add a Remote Repository

git remote add origin https://github.com/username/repository.git

(b) Push to a Remote Repository

git push -u origin main

(c) Pull from a Remote Repository

git pull origin main

8.2.10 Best Practices for Using Git

(a) Commit Often: Make small, frequent commits with clear messages.
(b) Write Good Commit Messages: Use descriptive messages that explain the changes.
(c) Use Branches: Create branches for new features or bug fixes.
(d) Review Changes: Use git diff to review changes before committing.
(e) Sync Regularly: Pull changes from the remote repository frequently to avoid
conflicts.

8.2.11 Summary

Git is an essential tool for version control, enabling you to track changes, collaborate with
others, and manage your code effectively. By mastering basic Git commands and
workflows, you can improve your productivity and ensure the integrity of your projects.
Appendices

Appendix A: C++ Standards Overview

• C++11: Introduction of auto, range-based for loops, smart pointers, and lambda
expressions.

• C++14: Generalized lambda captures, return type deduction, and binary literals.

• C++17: Structured bindings, std::optional, std::variant, and parallel algorithms.

• C++20: Concepts, ranges, coroutines, and modules.

• C++23: Expected features and improvements (e.g., std::expected, std::mdspan).

Appendix B: Compiler Installation Guides

(a) GCC (GNU Compiler Collection)

• Installation on Linux: sudo apt install g++


• Installation on Windows (via MinGW): MinGW Installation Guide
• Installation on macOS: brew install gcc

(b) Clang

156
157

• Installation on Linux: sudo apt install clang


• Installation on Windows: Clang for Windows
• Installation on macOS: brew install llvm

(c) MSVC (Microsoft Visual C++)

• Installation via Visual Studio: Visual Studio Download

Appendix C: IDE Setup Guides

(a) Visual Studio

• Download and install from Visual Studio.


• Configure C++ development workload.

(b) CLion

• Download and install from JetBrains CLion.


• Set up toolchains (GCC, Clang, or MSVC).

(c) VS Code

• Download and install from VS Code.


• Install C++ extensions (C/C++ IntelliSense, CMake Tools).

Appendix D: CMake Basics

• What is CMake?
A cross-platform build system for managing C++ projects.

• Basic CMake Commands:


158

cmake_minimum_required(VERSION 3.10)
project(MyProject)
add_executable(MyProgram main.cpp)

• Building a Project:

mkdir build
cd build
cmake ..
make

Appendix E: Debugging Tools

(a) GDB (GNU Debugger)

• Basic commands:
– gdb ./my program
– break main
– run
– print variable name

(b) IDE Debuggers

• Visual Studio: Use the built-in debugger with breakpoints and watch windows.
• CLion: Integrated GDB/LLDB support.
• VS Code: Use the C++ debugger extension.
159

Appendix F: Git Basics

• Initializing a Repository:

git init
git add .
git commit -m "Initial commit"

• Cloning a Repository:

git clone <repository_url>

• Basic Commands:

– git status
– git pull
– git push
– git branch

Appendix G: Additional Resources

(a) Books:

• ”C++ Primer” by Stanley B. Lippman


• ”Programming: Principles and Practice Using C++” by Bjarne Stroustrup

(b) Websites:

• cppreference.com
• isocpp.org
160

(c) Online Tutorials:

• LearnCpp.com
• GeeksforGeeks C++ Programming

Appendix H: Sample Programs

(a) Hello World:

#include <iostream>
int main() {
std::cout << "Hello, World!" << std::endl;
return 0;
}

(b) Simple Calculator:

#include <iostream>
int main() {
double a, b;
char op;
std::cout << "Enter two numbers and an operator (+, -, *, /):
,→ ";
std::cin >> a >> b >> op;
switch (op) {
case '+': std::cout << "Result: " << a + b << std::endl;
,→ break;
case '-': std::cout << "Result: " << a - b << std::endl;
,→ break;
case '*': std::cout << "Result: " << a * b << std::endl;
,→ break;
161

case '/': std::cout << "Result: " << a / b << std::endl;


,→ break;
default: std::cout << "Invalid operator!" << std::endl;
}
return 0;
}

(c) Number Guessing Game:

#include <iostream>
#include <cstdlib>
#include <ctime>
int main() {
std::srand(std::time(0));
int number = std::rand() % 100 + 1;
int guess;
std::cout << "Guess a number between 1 and 100: ";
while (std::cin >> guess) {
if (guess < number) std::cout << "Too low! Try again: ";
else if (guess > number) std::cout << "Too high! Try
,→ again: ";
else {
std::cout << "Correct! You win!" << std::endl;
break;
}
}
return 0;
}
References

Books:

(a) ”The C++ Programming Language” by Bjarne Stroustrup

• The definitive guide to C++ by its creator. A must-read for understanding the
language in depth.

(b) ”Effective Modern C++” by Scott Meyers

• Focuses on best practices and modern C++ features (C++11, C++14, and
beyond).

(c) ”C++ Primer” by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo

• A comprehensive introduction to C++ for beginners and intermediate


programmers.

(d) ”Accelerated C++” by Andrew Koenig and Barbara E. Moo

• A practical and fast-paced introduction to C++.

(e) ”Programming: Principles and Practice Using C++” by Bjarne Stroustrup

• A beginner-friendly book that teaches programming concepts using C++.

(f) ”Effective STL” by Scott Meyers

162
163

• A guide to using the Standard Template Library (STL) effectively.


(g) ”Modern C++ Design” by Andrei Alexandrescu
• Explores advanced C++ techniques and design patterns.

Websites and Online Resources:

(a) cppreference.com
• A comprehensive and reliable online reference for the C++ standard library and
language features.
(b) isocpp.org
• The official website for the C++ programming language, maintained by the ISO
C++ Foundation.
(c) Stack Overflow (C++ Tag)
• A community-driven Q&A platform for solving specific C++ problems and
learning from others.
(d) LearnCpp.com
• A beginner-friendly tutorial website for learning C++.
(e) GeeksforGeeks C++ Programming Language
• A resource for tutorials, articles, and coding challenges in C++.
(f) C++ Core Guidelines
• A set of guidelines for writing modern and maintainable C++ code, maintained
by Bjarne Stroustrup and Herb Sutter.
(g) Google C++ Style Guide
• A widely used style guide for writing clean and consistent C++ code.
164

Tools and Compilers:

(a) GCC (GNU Compiler Collection)

• A popular open-source compiler for C++.

(b) Clang/LLVM

• A modern compiler with excellent diagnostics and support for C++ standards.

(c) Microsoft Visual Studio

• An IDE with robust support for C++ development, including debugging and
profiling tools.

(d) Compiler Explorer (godbolt.org)

• An online tool to explore and compare compiler outputs for C++ code.

AI and Code Assistance Tools:

(a) ChatGPT (OpenAI)

• Useful for generating code snippets, explaining concepts, and debugging.

(b) DeepSeek AI

• An AI-powered tool designed to assist with code generation, optimization, and


learning C++ concepts.

(c) Gemini

• An AI assistant that provides code suggestions, debugging help, and


explanations for C++ programming.

(d) GitHub Copilot


165

• An AI-powered code completion tool that can assist with writing C++ code.

(e) Replit (AI Features)

• An online IDE with AI-assisted coding capabilities.

Additional Resources:

(a) C++ Weekly (YouTube Channel by Jason Turner)

• Short, informative videos on modern C++ features and best practices.

(b) CppCon (Conference Talks)

• Annual C++ conference with talks on advanced topics and modern C++
techniques.

(c) Boost C++ Libraries

• A collection of peer-reviewed, open-source C++ libraries.

(d) The Cherno (YouTube Channel)

• Tutorials and deep dives into C++ and game development.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy