├── .gitignore ├── 2DGameDev.md ├── BruteForce.cpp ├── C++ Basics ├── cpp_arrays.cpp ├── cpp_basic_syntax.cpp ├── cpp_calculator.cpp ├── cpp_conditional_statements.cpp ├── cpp_dynamic_memory_allocation.cpp ├── cpp_file_handling.cpp ├── cpp_functions.cpp ├── cpp_loops.cpp ├── cpp_pointers.cpp ├── cpp_preprocessor_directives.cpp ├── cpp_strings.cpp ├── cpp_structures_and_unions.cpp └── cpp_variable_scope_lifetime.cpp ├── Casting in C++ └── casting_cpp.cpp ├── Cpp_cheatsheet └── C++CheatSheet - V1.pdf ├── CreateDLL ├── MyDLL.cpp ├── MyDLL.dll ├── MyDLL.hpp ├── main.cpp └── readme.md ├── Debugging ├── main.cpp └── readme.md ├── Labs ├── 01_Digits.cpp ├── 02_fibonacci.cpp ├── 03_prime.cpp ├── 04_gcd.cpp ├── 05_merging_vectors.cpp └── 06_average_it_vec.cpp ├── OOP Projects └── LibraryManagement │ ├── ATM │ └── atm.cpp │ ├── Main.cpp │ ├── Makefile │ ├── SimpleProject.cpp │ ├── headers │ ├── Book.h │ ├── Library.h │ └── Member.h │ ├── readme.md │ ├── sources │ ├── Book.cpp │ ├── Library.cpp │ └── Member.cpp │ └── uml.drawio ├── Object Oriented Programming ├── move_semantics.cpp └── oop.md ├── Other Projects └── Sudoko.cpp ├── Pointers & References ├── Pointers │ ├── 02_pointer_arithmetic.cpp │ ├── 03_pointer_to_pointer.cpp │ ├── 04_pointers_and_arrays.cpp │ ├── 05_pointers_and_functions.cpp │ ├── 06_void_pointers.cpp │ ├── 07_null_and_dangling_pointers.cpp │ ├── 08_const_pointers.cpp │ ├── 09_function_pointers.cpp │ ├── 10_smart_pointers.cpp │ └── README.md └── References │ ├── 01_basics_of_references.cpp │ ├── 02_references_and_functions.cpp │ ├── 03_references_and_return_values.cpp │ ├── 04_const_references.cpp │ ├── 05_references_vs_pointers.cpp │ ├── 06_rvalue_references.cpp │ └── README.md ├── Pointers&References └── Pointers │ └── 01_basics_of_pointers.cpp ├── README.md ├── STL (Standard Template Library) ├── Algorithms │ └── using_algorithms.cpp ├── Containers │ ├── Associative Containers │ │ ├── 01_set.cpp │ │ ├── 02_multiset.cpp │ │ ├── 03_map.cpp │ │ └── 04_multimap.cpp │ ├── Container Adapters │ │ ├── 01_stack.cpp │ │ ├── 02_queue.cpp │ │ └── 03_priority_queue.cpp │ ├── Sequence Containers │ │ ├── 01_vector_construct.cpp │ │ ├── 02_vector_element_access.cpp │ │ ├── 03_vector_modifiers.cpp │ │ ├── 04_vector_in_place_construction.cpp │ │ ├── 05_array_basic_usage.cpp │ │ ├── 06_array_modify_and_iterators.cpp │ │ ├── 07_array_multidimensional.cpp │ │ ├── 08_array_functions.cpp │ │ ├── 09_deque_basic_usage.cpp │ │ ├── 10_deque_modify_and_iterators.cpp │ │ ├── 11_deque_algorithms.cpp │ │ ├── 12_deque_multidimensional.cpp │ │ ├── 13_forward_list_basic_usage.cpp │ │ ├── 14_forward_list_modify_and_iterators.cpp │ │ ├── 15_forward_list_algorithms.cpp │ │ ├── 16_list_basic_usage.cpp │ │ ├── 17_list_modify_and_iterators.cpp │ │ └── 18_list_algorithms.cpp │ ├── Unordered Associative Containers │ │ ├── 01_unordered_set.cpp │ │ ├── 02_unordered_multiset.cpp │ │ ├── 03_unordered_map.cpp │ │ └── 04_unordered_multimap.cpp │ ├── readme.md │ └── sequence_containers.png └── Iterators │ ├── readme.md │ └── using_iterators.cpp ├── Smart Pointers ├── shared_ptr.cpp └── unique_ptr.cpp ├── StaticDynamicCourse.md ├── hackMe.cpp └── modern C++ ├── CPP11.md ├── CPP14.md ├── CPP17.md ├── CPP20.md ├── ModernC++.md ├── README.md ├── range_loops.md └── uniform_initialization.md /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # executables 7 | *.exe 8 | 9 | # User-specific files 10 | *.rsuser 11 | *.suo 12 | *.user 13 | *.userosscache 14 | *.sln.docstates 15 | 16 | # User-specific files (MonoDevelop/Xamarin Studio) 17 | *.userprefs 18 | 19 | # Mono auto generated files 20 | mono_crash.* 21 | 22 | # Build results 23 | [Dd]ebug/ 24 | [Dd]ebugPublic/ 25 | [Rr]elease/ 26 | [Rr]eleases/ 27 | x64/ 28 | x86/ 29 | [Ww][Ii][Nn]32/ 30 | [Aa][Rr][Mm]/ 31 | [Aa][Rr][Mm]64/ 32 | bld/ 33 | [Bb]in/ 34 | [Oo]bj/ 35 | [Ll]og/ 36 | [Ll]ogs/ 37 | 38 | # Visual Studio 2015/2017 cache/options directory 39 | .vs/ 40 | # Uncomment if you have tasks that create the project's static files in wwwroot 41 | #wwwroot/ 42 | 43 | # Visual Studio 2017 auto generated files 44 | Generated\ Files/ 45 | 46 | # MSTest test Results 47 | [Tt]est[Rr]esult*/ 48 | [Bb]uild[Ll]og.* 49 | 50 | # NUnit 51 | *.VisualState.xml 52 | TestResult.xml 53 | nunit-*.xml 54 | 55 | # Build Results of an ATL Project 56 | [Dd]ebugPS/ 57 | [Rr]eleasePS/ 58 | dlldata.c 59 | 60 | # Benchmark Results 61 | BenchmarkDotNet.Artifacts/ 62 | 63 | # .NET Core 64 | project.lock.json 65 | project.fragment.lock.json 66 | artifacts/ 67 | 68 | # ASP.NET Scaffolding 69 | ScaffoldingReadMe.txt 70 | 71 | # StyleCop 72 | StyleCopReport.xml 73 | 74 | # Files built by Visual Studio 75 | *_i.c 76 | *_p.c 77 | *_h.h 78 | *.ilk 79 | *.meta 80 | *.obj 81 | *.iobj 82 | *.pch 83 | *.pdb 84 | *.ipdb 85 | *.pgc 86 | *.pgd 87 | *.rsp 88 | *.sbr 89 | *.tlb 90 | *.tli 91 | *.tlh 92 | *.tmp 93 | *.tmp_proj 94 | *_wpftmp.csproj 95 | *.log 96 | *.tlog 97 | *.vspscc 98 | *.vssscc 99 | .builds 100 | *.pidb 101 | *.svclog 102 | *.scc 103 | 104 | # Chutzpah Test files 105 | _Chutzpah* 106 | 107 | # Visual C++ cache files 108 | ipch/ 109 | *.aps 110 | *.ncb 111 | *.opendb 112 | *.opensdf 113 | *.sdf 114 | *.cachefile 115 | *.VC.db 116 | *.VC.VC.opendb 117 | 118 | # Visual Studio profiler 119 | *.psess 120 | *.vsp 121 | *.vspx 122 | *.sap 123 | 124 | # Visual Studio Trace Files 125 | *.e2e 126 | 127 | # TFS 2012 Local Workspace 128 | $tf/ 129 | 130 | # Guidance Automation Toolkit 131 | *.gpState 132 | 133 | # ReSharper is a .NET coding add-in 134 | _ReSharper*/ 135 | *.[Rr]e[Ss]harper 136 | *.DotSettings.user 137 | 138 | # TeamCity is a build add-in 139 | _TeamCity* 140 | 141 | # DotCover is a Code Coverage Tool 142 | *.dotCover 143 | 144 | # AxoCover is a Code Coverage Tool 145 | .axoCover/* 146 | !.axoCover/settings.json 147 | 148 | # Coverlet is a free, cross platform Code Coverage Tool 149 | coverage*.json 150 | coverage*.xml 151 | coverage*.info 152 | 153 | # Visual Studio code coverage results 154 | *.coverage 155 | *.coveragexml 156 | 157 | # NCrunch 158 | _NCrunch_* 159 | .*crunch*.local.xml 160 | nCrunchTemp_* 161 | 162 | # MightyMoose 163 | *.mm.* 164 | AutoTest.Net/ 165 | 166 | # Web workbench (sass) 167 | .sass-cache/ 168 | 169 | # Installshield output folder 170 | [Ee]xpress/ 171 | 172 | # DocProject is a documentation generator add-in 173 | DocProject/buildhelp/ 174 | DocProject/Help/*.HxT 175 | DocProject/Help/*.HxC 176 | DocProject/Help/*.hhc 177 | DocProject/Help/*.hhk 178 | DocProject/Help/*.hhp 179 | DocProject/Help/Html2 180 | DocProject/Help/html 181 | 182 | # Click-Once directory 183 | publish/ 184 | 185 | # Publish Web Output 186 | *.[Pp]ublish.xml 187 | *.azurePubxml 188 | # Note: Comment the next line if you want to checkin your web deploy settings, 189 | # but database connection strings (with potential passwords) will be unencrypted 190 | *.pubxml 191 | *.publishproj 192 | 193 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 194 | # checkin your Azure Web App publish settings, but sensitive information contained 195 | # in these scripts will be unencrypted 196 | PublishScripts/ 197 | 198 | # NuGet Packages 199 | *.nupkg 200 | # NuGet Symbol Packages 201 | *.snupkg 202 | # The packages folder can be ignored because of Package Restore 203 | **/[Pp]ackages/* 204 | # except build/, which is used as an MSBuild target. 205 | !**/[Pp]ackages/build/ 206 | # Uncomment if necessary however generally it will be regenerated when needed 207 | #!**/[Pp]ackages/repositories.config 208 | # NuGet v3's project.json files produces more ignorable files 209 | *.nuget.props 210 | *.nuget.targets 211 | 212 | # Microsoft Azure Build Output 213 | csx/ 214 | *.build.csdef 215 | 216 | # Microsoft Azure Emulator 217 | ecf/ 218 | rcf/ 219 | 220 | # Windows Store app package directories and files 221 | AppPackages/ 222 | BundleArtifacts/ 223 | Package.StoreAssociation.xml 224 | _pkginfo.txt 225 | *.appx 226 | *.appxbundle 227 | *.appxupload 228 | 229 | # Visual Studio cache files 230 | # files ending in .cache can be ignored 231 | *.[Cc]ache 232 | # but keep track of directories ending in .cache 233 | !?*.[Cc]ache/ 234 | 235 | # Others 236 | ClientBin/ 237 | ~$* 238 | *~ 239 | *.dbmdl 240 | *.dbproj.schemaview 241 | *.jfm 242 | *.pfx 243 | *.publishsettings 244 | orleans.codegen.cs 245 | 246 | # Including strong name files can present a security risk 247 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 248 | #*.snk 249 | 250 | # Since there are multiple workflows, uncomment next line to ignore bower_components 251 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 252 | #bower_components/ 253 | 254 | # RIA/Silverlight projects 255 | Generated_Code/ 256 | 257 | # Backup & report files from converting an old project file 258 | # to a newer Visual Studio version. Backup files are not needed, 259 | # because we have git ;-) 260 | _UpgradeReport_Files/ 261 | Backup*/ 262 | UpgradeLog*.XML 263 | UpgradeLog*.htm 264 | ServiceFabricBackup/ 265 | *.rptproj.bak 266 | 267 | # SQL Server files 268 | *.mdf 269 | *.ldf 270 | *.ndf 271 | 272 | # Business Intelligence projects 273 | *.rdl.data 274 | *.bim.layout 275 | *.bim_*.settings 276 | *.rptproj.rsuser 277 | *- [Bb]ackup.rdl 278 | *- [Bb]ackup ([0-9]).rdl 279 | *- [Bb]ackup ([0-9][0-9]).rdl 280 | 281 | # Microsoft Fakes 282 | FakesAssemblies/ 283 | 284 | # GhostDoc plugin setting file 285 | *.GhostDoc.xml 286 | 287 | # Node.js Tools for Visual Studio 288 | .ntvs_analysis.dat 289 | node_modules/ 290 | 291 | # Visual Studio 6 build log 292 | *.plg 293 | 294 | # Visual Studio 6 workspace options file 295 | *.opt 296 | 297 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 298 | *.vbw 299 | 300 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 301 | *.vbp 302 | 303 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 304 | *.dsw 305 | *.dsp 306 | 307 | # Visual Studio 6 technical files 308 | *.ncb 309 | *.aps 310 | 311 | # Visual Studio LightSwitch build output 312 | **/*.HTMLClient/GeneratedArtifacts 313 | **/*.DesktopClient/GeneratedArtifacts 314 | **/*.DesktopClient/ModelManifest.xml 315 | **/*.Server/GeneratedArtifacts 316 | **/*.Server/ModelManifest.xml 317 | _Pvt_Extensions 318 | 319 | # Paket dependency manager 320 | .paket/paket.exe 321 | paket-files/ 322 | 323 | # FAKE - F# Make 324 | .fake/ 325 | 326 | # CodeRush personal settings 327 | .cr/personal 328 | 329 | # Python Tools for Visual Studio (PTVS) 330 | __pycache__/ 331 | *.pyc 332 | 333 | # Cake - Uncomment if you are using it 334 | # tools/** 335 | # !tools/packages.config 336 | 337 | # Tabs Studio 338 | *.tss 339 | 340 | # Telerik's JustMock configuration file 341 | *.jmconfig 342 | 343 | # BizTalk build output 344 | *.btp.cs 345 | *.btm.cs 346 | *.odx.cs 347 | *.xsd.cs 348 | 349 | # OpenCover UI analysis results 350 | OpenCover/ 351 | 352 | # Azure Stream Analytics local run output 353 | ASALocalRun/ 354 | 355 | # MSBuild Binary and Structured Log 356 | *.binlog 357 | 358 | # NVidia Nsight GPU debugger configuration file 359 | *.nvuser 360 | 361 | # MFractors (Xamarin productivity tool) working folder 362 | .mfractor/ 363 | 364 | # Local History for Visual Studio 365 | .localhistory/ 366 | 367 | # Visual Studio History (VSHistory) files 368 | .vshistory/ 369 | 370 | # BeatPulse healthcheck temp database 371 | healthchecksdb 372 | 373 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 374 | MigrationBackup/ 375 | 376 | # Ionide (cross platform F# VS Code tools) working folder 377 | .ionide/ 378 | 379 | # Fody - auto-generated XML schema 380 | FodyWeavers.xsd 381 | 382 | # VS Code files for those working on multiple tools 383 | .vscode/* 384 | !.vscode/settings.json 385 | !.vscode/tasks.json 386 | !.vscode/launch.json 387 | !.vscode/extensions.json 388 | *.code-workspace 389 | 390 | # Local History for Visual Studio Code 391 | .history/ 392 | 393 | # Windows Installer files from build outputs 394 | *.cab 395 | *.msi 396 | *.msix 397 | *.msm 398 | *.msp 399 | 400 | # JetBrains Rider 401 | *.sln.iml 402 | 403 | -------------------------------------------------------------------------------- /2DGameDev.md: -------------------------------------------------------------------------------- 1 | The book : https://unglueit-files.s3.amazonaws.com/ebf/ee0225ec966b4910a0882f4e388c8bdf.pdf 2 | 3 | # SFML and Visual Studio 4 | - First, you must download the SFML SDK from the [download page](https://www.sfml-dev.org/download.php). 5 | ![image](https://github.com/user-attachments/assets/13abfba7-11ea-4c75-b7ad-1b21904a2074) 6 | ![image](https://github.com/user-attachments/assets/a263ee7a-65e9-4674-8646-0b6292e9c733) 7 | 8 | #include 9 | ```cpp 10 | int main() 11 | { 12 | sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); 13 | sf::CircleShape shape(100.f); 14 | shape.setFillColor(sf::Color::Green); 15 | 16 | while (window.isOpen()) 17 | { 18 | sf::Event event; 19 | while (window.pollEvent(event)) 20 | { 21 | if (event.type == sf::Event::Closed) 22 | window.close(); 23 | } 24 | 25 | window.clear(); 26 | window.draw(shape); 27 | window.display(); 28 | } 29 | 30 | return 0; 31 | } 32 | ``` 33 | # System module 34 | ## Handling time 35 | A sf::Time value can be constructed from different source units: seconds, milliseconds and microseconds. 36 | ```cpp 37 | sf::Time t1 = sf::microseconds(10000); 38 | sf::Time t2 = sf::milliseconds(10); 39 | sf::Time t3 = sf::seconds(0.01f); 40 | ``` 41 | Measuring time : 42 | ```cpp 43 | sf::Clock clock; // starts the clock 44 | ... 45 | sf::Time elapsed1 = clock.getElapsedTime(); 46 | std::cout << elapsed1.asSeconds() << std::endl; 47 | clock.restart(); 48 | ... 49 | sf::Time elapsed2 = clock.getElapsedTime(); 50 | std::cout << elapsed2.asSeconds() << std::endl; 51 | ``` 52 | # Window module 53 | Windows in SFML are defined by the sf::Window class. A window can be created and opened directly upon construction: 54 | ```cpp 55 | #include 56 | 57 | int main() 58 | { 59 | sf::Window window(sf::VideoMode(800, 600), "My window"); 60 | 61 | ... 62 | 63 | return 0; 64 | } 65 | ``` 66 | - The first argument, the video mode, defines the size of the window (the inner size, without the title bar and borders). Here, we create a window with a size of 800x600 pixels. 67 | - The second argument is simply the title of the window. 68 | - This constructor accepts a third optional argument: a style, which allows you to choose which decorations and features you want. 69 | ![image](https://github.com/user-attachments/assets/7e3fffeb-4908-486e-803f-ffe8381c5b0b) 70 | 71 | ## Bringing the window to life 72 | - If you try to execute the code above with nothing in place of the "...", you will hardly see something. First, because the program ends immediately. Second, because there's no event handling -- so even if you added an endless loop to this code, you would see a dead window, unable to be moved, resized, or closed. 73 | ```cpp 74 | #include 75 | 76 | int main() 77 | { 78 | sf::Window window(sf::VideoMode(800, 600), "My window"); 79 | 80 | // run the program as long as the window is open 81 | while (window.isOpen()) 82 | { 83 | // check all the window's events that were triggered since the last iteration of the loop 84 | sf::Event event; 85 | while (window.pollEvent(event)) 86 | { 87 | // "close requested" event: we close the window 88 | if (event.type == sf::Event::Closed) 89 | window.close(); 90 | } 91 | } 92 | 93 | return 0; 94 | } 95 | ``` 96 | ## Playing with the window 97 | - Of course, SFML allows you to play with your windows a bit. Basic window operations such as changing the size, position, title or icon are supported, but unlike dedicated GUI libraries (Qt, wxWidgets), SFML doesn't provide advanced features. SFML windows are only meant to provide an environment for OpenGL or SFML drawing. 98 | ```cpp 99 | // change the position of the window (relatively to the desktop) 100 | window.setPosition(sf::Vector2i(10, 50)); 101 | 102 | // change the size of the window 103 | window.setSize(sf::Vector2u(640, 480)); 104 | 105 | // change the title of the window 106 | window.setTitle("SFML window"); 107 | 108 | // get the size of the window 109 | sf::Vector2u size = window.getSize(); 110 | unsigned int width = size.x; 111 | unsigned int height = size.y; 112 | 113 | // check whether the window has the focus 114 | bool focus = window.hasFocus(); 115 | 116 | ... 117 | ``` 118 | Refer to https://www.sfml-dev.org/documentation/2.6.1/classsf_1_1Window.php for more details! 119 | ## Controlling the framerate 120 | Sometimes, when your application runs fast, you may notice visual artifacts such as tearing. The reason is that your application's refresh rate is not synchronized with the vertical frequency of the monitor, and as a result, the bottom of the previous frame is mixed with the top of the next one. 121 | The solution to this problem is to activate vertical synchronization. It is automatically handled by the graphics card, and can easily be switched on and off with the setVerticalSyncEnabled function: 122 | ```cpp 123 | window.setVerticalSyncEnabled(true); // call it once, after creating the window 124 | ``` 125 | After this call, your application will run at the same frequency as the monitor's refresh rate. 126 | In other situations, you may also want your application to run at a given framerate, instead of the monitor's frequency. This can be done by calling setFramerateLimit: 127 | ```cpp 128 | window.setFramerateLimit(60); // call it once, after creating the window 129 | ``` 130 | # Events 131 | Before dealing with events, it is important to understand what the sf::Event type is, and how to correctly use it. sf::Event is a union, which means that only one of its members is valid at a time (remember your C++ lesson: all the members of a union share the same memory space). The valid member is the one that matches the event type, for example event.key for a KeyPressed event. Trying to read any other member will result in an undefined behavior (most likely: random or invalid values). It is important to never try to use an event member that doesn't match its type. 132 | 133 | sf::Event instances are filled by the pollEvent (or waitEvent) function of the sf::Window class. Only these two functions can produce valid events, any attempt to use an sf::Event which was not returned by successful call to pollEvent (or waitEvent) will result in the same undefined behavior that was mentioned above. 134 | 135 | To be clear, here is what a typical event loop looks like: 136 | ```cpp 137 | sf::Event event; 138 | 139 | // while there are pending events... 140 | while (window.pollEvent(event)) 141 | { 142 | // check the type of the event... 143 | switch (event.type) 144 | { 145 | // window closed 146 | case sf::Event::Closed: 147 | window.close(); 148 | break; 149 | 150 | // key pressed 151 | case sf::Event::KeyPressed: 152 | ... 153 | break; 154 | 155 | // we don't process other types of events 156 | default: 157 | break; 158 | } 159 | } 160 | ``` 161 | ## The Closed event 162 | The sf::Event::Closed event is triggered when the user wants to close the window, through any of the possible methods the window manager provides ("close" button, keyboard shortcut, etc.). This event only represents a close request, the window is not yet closed when the event is received. 163 | 164 | Typical code will just call window.close() in reaction to this event, to actually close the window. However, you may also want to do something else first, like saving the current application state or asking the user what to do. If you don't do anything, the window remains open. 165 | 166 | There's no member associated with this event in the sf::Event union. 167 | ```cpp 168 | if (event.type == sf::Event::Closed) 169 | window.close(); 170 | ``` 171 | ## The Resized event 172 | ```cpp 173 | if (event.type == sf::Event::Resized) 174 | { 175 | std::cout << "new width: " << event.size.width << std::endl; 176 | std::cout << "new height: " << event.size.height << std::endl; 177 | } 178 | ``` 179 | ## The LostFocus and GainedFocus events 180 | The sf::Event::LostFocus and sf::Event::GainedFocus events are triggered when the window loses/gains focus, which happens when the user switches the currently active window. When the window is out of focus, it doesn't receive keyboard events. 181 | 182 | This event can be used e.g. if you want to pause your game when the window is inactive. 183 | 184 | There's no member associated with these events in the sf::Event union. 185 | ```cpp 186 | if (event.type == sf::Event::LostFocus) 187 | myGame.pause(); 188 | 189 | if (event.type == sf::Event::GainedFocus) 190 | myGame.resume(); 191 | ``` 192 | ## The MouseEntered and MouseLeft event 193 | The sf::Event::MouseEntered and sf::Event::MouseLeft events are triggered when the mouse cursor enters/leaves the window. 194 | 195 | There's no member associated with these events in the sf::Event union. 196 | ```cpp 197 | if (event.type == sf::Event::MouseEntered) 198 | std::cout << "the mouse cursor has entered the window" << std::endl; 199 | 200 | if (event.type == sf::Event::MouseLeft) 201 | std::cout << "the mouse cursor has left the window" << std::endl; 202 | ``` 203 | ## The JoystickButtonPressed and JoystickButtonReleased events 204 | The sf::Event::JoystickButtonPressed and sf::Event::JoystickButtonReleased events are triggered when a joystick button is pressed/released. 205 | 206 | SFML supports up to 8 joysticks and 32 buttons. 207 | 208 | The member associated with these events is event.joystickButton, it contains the identifier of the joystick and the index of the pressed/released button. 209 | ```cpp 210 | if (event.type == sf::Event::JoystickButtonPressed) 211 | { 212 | std::cout << "joystick button pressed!" << std::endl; 213 | std::cout << "joystick id: " << event.joystickButton.joystickId << std::endl; 214 | std::cout << "button: " << event.joystickButton.button << std::endl; 215 | } 216 | ``` 217 | # Keyboard, mouse and joystick 218 | ## Keyboard 219 | ```cpp 220 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) 221 | { 222 | // left key is pressed: move our character 223 | character.move(-1.f, 0.f); 224 | } 225 | ``` 226 | ```cpp 227 | if (sf::Keyboard::isKeyPressed(sf::Keyboard::Scan::Right)) 228 | { 229 | // right key is pressed: move our character 230 | character.move(1.f, 0.f); 231 | } 232 | ``` 233 | ## Mouse 234 | ```cpp 235 | if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) 236 | { 237 | // left mouse button is pressed: shoot 238 | gun.fire(); 239 | } 240 | ``` 241 | You can also get and set the current position of the mouse, either relative to the desktop or to a window: 242 | ```cpp 243 | // get the global mouse position (relative to the desktop) 244 | sf::Vector2i globalPosition = sf::Mouse::getPosition(); 245 | 246 | // get the local mouse position (relative to a window) 247 | sf::Vector2i localPosition = sf::Mouse::getPosition(window); // window is a sf::Window 248 | ``` 249 | ```cpp 250 | // set the mouse position globally (relative to the desktop) 251 | sf::Mouse::setPosition(sf::Vector2i(10, 50)); 252 | 253 | // set the mouse position locally (relative to a window) 254 | sf::Mouse::setPosition(sf::Vector2i(10, 50), window); // window is a sf::Window 255 | ``` 256 | ## Joystick 257 | ```cpp 258 | if (sf::Joystick::isConnected(0)) 259 | { 260 | // joystick number 0 is connected 261 | ... 262 | } 263 | ``` 264 | # Graphics module 265 | To draw the entities provided by the graphics module, you must use a specialized window class: sf::RenderWindow. This class is derived from sf::Window, and inherits all its functions. Everything that you've learnt about sf::Window (creation, event handling, controlling the framerate, mixing with OpenGL, etc.) is applicable to sf::RenderWindow as well. 266 | 267 | On top of that, sf::RenderWindow adds high-level functions to help you draw things easily. In this tutorial we'll focus on two of these functions: clear and draw. They are as simple as their name implies: clear clears the whole window with the chosen color, and draw draws whatever object you pass to it. 268 | 269 | Here is what a typical main loop looks like with a render window: 270 | ```cpp 271 | #include 272 | 273 | int main() 274 | { 275 | // create the window 276 | sf::RenderWindow window(sf::VideoMode(800, 600), "My window"); 277 | 278 | // run the program as long as the window is open 279 | while (window.isOpen()) 280 | { 281 | // check all the window's events that were triggered since the last iteration of the loop 282 | sf::Event event; 283 | while (window.pollEvent(event)) 284 | { 285 | // "close requested" event: we close the window 286 | if (event.type == sf::Event::Closed) 287 | window.close(); 288 | } 289 | 290 | // clear the window with black color 291 | window.clear(sf::Color::Black); 292 | 293 | // draw everything here... 294 | // window.draw(...); 295 | 296 | // end the current frame 297 | window.display(); 298 | } 299 | 300 | return 0; 301 | } 302 | ``` 303 | ## Position, rotation, scale: Transforming entities 304 | ### Position 305 | ```cpp 306 | // 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class 307 | 308 | // set the absolute position of the entity 309 | entity.setPosition(10.f, 50.f); 310 | 311 | // move the entity relatively to its current position 312 | entity.move(5.f, 5.f); 313 | 314 | // retrieve the absolute position of the entity 315 | sf::Vector2f position = entity.getPosition(); // = (15, 55) 316 | ``` 317 | ### Rotation 318 | ```cpp 319 | // 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class 320 | 321 | // set the absolute rotation of the entity 322 | entity.setRotation(45.f); 323 | 324 | // rotate the entity relatively to its current orientation 325 | entity.rotate(10.f); 326 | 327 | // retrieve the absolute rotation of the entity 328 | float rotation = entity.getRotation(); // = 55 329 | ``` 330 | ### Scale 331 | ```cpp 332 | // 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class 333 | 334 | // set the absolute scale of the entity 335 | entity.setScale(4.f, 1.6f); 336 | 337 | // scale the entity relatively to its current scale 338 | entity.scale(0.5f, 0.5f); 339 | 340 | // retrieve the absolute scale of the entity 341 | sf::Vector2f scale = entity.getScale(); // = (2, 0.8) 342 | ``` 343 | ### Origin 344 | ```cpp 345 | // 'entity' can be a sf::Sprite, a sf::Text, a sf::Shape or any other transformable class 346 | 347 | // set the origin of the entity 348 | entity.setOrigin(10.f, 20.f); 349 | 350 | // retrieve the origin of the entity 351 | sf::Vector2f origin = entity.getOrigin(); // = (10, 20) 352 | ``` 353 | ### Transforming your own classes 354 | ```cpp 355 | class MyGraphicalEntity : public sf::Transformable 356 | { 357 | // ... 358 | }; 359 | 360 | MyGraphicalEntity entity; 361 | entity.setPosition(10.f, 30.f); 362 | entity.setRotation(110.f); 363 | entity.setScale(0.5f, 0.2f); 364 | ``` 365 | ### Bounding boxes 366 | After transforming entities and drawing them, you might want to perform some computations using them e.g. checking for collisions. 367 | 368 | SFML entities can give you their bounding box. The bounding box is the minimal rectangle that contains all points belonging to the entity, with sides aligned to the X and Y axes. 369 | 370 | ```cpp 371 | // get the bounding box of the entity 372 | sf::FloatRect boundingBox = entity.getGlobalBounds(); 373 | 374 | // check collision with a point 375 | sf::Vector2f point = ...; 376 | if (boundingBox.contains(point)) 377 | { 378 | // collision! 379 | } 380 | 381 | // check collision with another box (like the bounding box of another entity) 382 | sf::FloatRect otherBox = ...; 383 | if (boundingBox.intersects(otherBox)) 384 | { 385 | // collision! 386 | } 387 | ``` 388 | The function is named getGlobalBounds because it returns the bounding box of the entity in the global coordinate system, i.e. after all of its transformations (position, rotation, scale) have been applied. 389 | There's another function that returns the bounding box of the entity in its local coordinate system (before its transformations are applied): getLocalBounds. This function can be used to get the initial size of an entity, for example, or to perform more specific calculations. 390 | -------------------------------------------------------------------------------- /BruteForce.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | // Function to run the hackMe executable and check access 12 | bool softwareAccess(const string& attempt) { 13 | // Create pipes for communication 14 | int inputPipe[2]; // Pipe for input 15 | int outputPipe[2]; // Pipe for output 16 | 17 | // Create the pipes 18 | if (pipe(inputPipe) == -1) { 19 | cerr << "Pipe creation for input failed: " << strerror(errno) << endl; 20 | return false; 21 | } 22 | if (pipe(outputPipe) == -1) { 23 | cerr << "Pipe creation for output failed: " << strerror(errno) << endl; 24 | close(inputPipe[0]); 25 | close(inputPipe[1]); 26 | return false; 27 | } 28 | 29 | // Fork a child process 30 | pid_t pid = fork(); 31 | if (pid < 0) { 32 | cerr << "Fork failed: " << strerror(errno) << endl; 33 | close(inputPipe[0]); 34 | close(inputPipe[1]); 35 | close(outputPipe[0]); 36 | close(outputPipe[1]); 37 | return false; 38 | } 39 | 40 | if (pid == 0) { // Child process 41 | // Close unused pipe ends 42 | close(inputPipe[1]); // Close write end of input pipe 43 | close(outputPipe[0]); // Close read end of output pipe 44 | 45 | // Redirect stdin and stdout 46 | dup2(inputPipe[0], STDIN_FILENO); // Redirect stdin to inputPipe read end 47 | dup2(outputPipe[1], STDOUT_FILENO); // Redirect stdout to outputPipe write end 48 | 49 | // Execute the hackMe program 50 | execl("./hackMe", "hackMe", (char*)nullptr); 51 | 52 | // If exec fails 53 | cerr << "Exec failed: " << strerror(errno) << endl; 54 | exit(1); // Exit child process 55 | } else { // Parent process 56 | // Close unused pipe ends 57 | close(inputPipe[0]); // Close read end of input pipe 58 | close(outputPipe[1]); // Close write end of output pipe 59 | 60 | // Write the password attempt to the input pipe 61 | write(inputPipe[1], attempt.c_str(), attempt.size()); 62 | write(inputPipe[1], "\n", 1); // Add newline to simulate pressing enter 63 | close(inputPipe[1]); // Close the input pipe after writing 64 | 65 | // Read the output from the output pipe 66 | array buffer; 67 | string result; 68 | ssize_t bytesRead; 69 | 70 | while ((bytesRead = read(outputPipe[0], buffer.data(), buffer.size())) > 0) { 71 | result.append(buffer.data(), bytesRead); 72 | } 73 | 74 | // Close the output pipe after reading 75 | close(outputPipe[0]); 76 | 77 | // Wait for child process to finish 78 | waitpid(pid, nullptr, 0); 79 | 80 | // Check if the result contains "Access granted!" 81 | return result.find("Access granted!") != string::npos; 82 | } 83 | } 84 | 85 | // Generates the next password attempt 86 | void generateNextAttempt(string &attempt, const string &characters) { 87 | int length = attempt.size(); 88 | 89 | // Start from the last character of the attempt string 90 | for (int i = length - 1; i >= 0; --i) { 91 | // Find current character's position in `characters` 92 | int pos = characters.find(attempt[i]); 93 | 94 | // If it's the last character in `characters`, reset and carry over 95 | if (pos == characters.size() - 1) { 96 | attempt[i] = characters[0]; // Reset to the first character 97 | } else { 98 | // Move to the next character in `characters` 99 | attempt[i] = characters[pos + 1]; 100 | return; // Stop after incrementing one character 101 | } 102 | } 103 | } 104 | 105 | // Brute-force password cracker function 106 | void bruteForceCrack() { 107 | string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789&"; // Possible characters 108 | string attempt; 109 | 110 | // Start brute-force attempts 111 | for (int len = 1; len <= 5; ++len) { // Max length of 5 112 | attempt = string(len, characters[0]); // Initialize attempt string of size `len` 113 | 114 | while (true) { 115 | // Try to access software with current attempt 116 | if (softwareAccess(attempt)) { 117 | cout << "Password cracked: " << attempt << endl; 118 | return; 119 | } 120 | 121 | // Generate next combination 122 | generateNextAttempt(attempt, characters); 123 | 124 | // Break if we wrapped back to the starting combination for this length 125 | if (attempt == string(len, characters[0])) break; 126 | } 127 | } 128 | 129 | cout << "Password not found." << endl; 130 | } 131 | 132 | int main() { 133 | bruteForceCrack(); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /C++ Basics/cpp_arrays.cpp: -------------------------------------------------------------------------------- 1 | // arrays.cpp 2 | // Working with Arrays in C++ 3 | 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | 9 | // Definition and syntax 10 | int numbers[5]; // Declare an array of 5 integers 11 | 12 | // Accessing array elements 13 | numbers[0] = 10; // Assign values to array elements 14 | numbers[1] = 20; 15 | numbers[2] = 30; 16 | numbers[3] = 40; 17 | numbers[4] = 50; 18 | 19 | cout << "Array elements:" << endl; 20 | for (int i = 0; i < 5; i++) { 21 | cout << numbers[i] << " "; // Accessing array elements 22 | } 23 | cout << endl; 24 | 25 | // Multi-dimensional arrays 26 | int matrix[2][3] = { {1, 2, 3}, {4, 5, 6} }; // 2x3 matrix 27 | 28 | cout << "2x3 Matrix elements:" << endl; 29 | for (int i = 0; i < 2; i++) { 30 | for (int j = 0; j < 3; j++) { 31 | cout << matrix[i][j] << " "; // Accessing multi-dimensional array elements 32 | } 33 | cout << endl; 34 | } 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /C++ Basics/cpp_basic_syntax.cpp: -------------------------------------------------------------------------------- 1 | // cpp_basic_syntax.cpp 2 | // Basic Syntax in C++ 3 | 4 | #include // Required for cin, cout 5 | using namespace std; 6 | 7 | int main() { 8 | 9 | // Comments in C++ 10 | // Single-line comment 11 | 12 | /* 13 | Multi-line comment 14 | */ 15 | 16 | // Data Types 17 | int integer = 10; // Integer data type 18 | float decimal = 3.14f; // Float data type 19 | char character = 'A'; // Character data type 20 | bool is_true = true; // Boolean data type (true or false) 21 | 22 | // Variables and Constants 23 | int num = 20; // Variable (value can be changed) 24 | const float PI = 3.14159; // Constant (value cannot be changed) 25 | 26 | // Input/Output 27 | cout << "Enter a number: "; 28 | int userInput; 29 | cin >> userInput; // Taking input from the user 30 | cout << "You entered: " << userInput << endl; // Outputting the result 31 | 32 | // Operators 33 | // Arithmetic Operators: +, -, *, /, % 34 | int a = 10, b = 3; 35 | cout << "a + b = " << a + b << endl; // Addition 36 | cout << "a - b = " << a - b << endl; // Subtraction 37 | cout << "a * b = " << a * b << endl; // Multiplication 38 | cout << "a / b = " << a / b << endl; // Division 39 | cout << "a % b = " << a % b << endl; // Modulus 40 | 41 | // Logical Operators: && (AND), || (OR), ! (NOT) 42 | bool condition = (a > b) && (a != 0); // Logical AND 43 | cout << "Logical AND (a > b && a != 0): " << condition << endl; 44 | 45 | condition = (a < b) || (a == 10); // Logical OR 46 | cout << "Logical OR (a < b || a == 10): " << condition << endl; 47 | 48 | condition = !(a == 10); // Logical NOT 49 | cout << "Logical NOT !(a == 10): " << condition << endl; 50 | 51 | // Relational Operators: ==, !=, >, <, >=, <= 52 | cout << "Is a equal to b? " << (a == b) << endl; // Equality 53 | cout << "Is a not equal to b? " << (a != b) << endl; // Inequality 54 | cout << "Is a greater than b? " << (a > b) << endl; // Greater than 55 | cout << "Is a less than or equal to b? " << (a <= b) << endl; // Less than or equal to 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /C++ Basics/cpp_calculator.cpp: -------------------------------------------------------------------------------- 1 | // calculator.cpp 2 | #include 3 | #include // for std::atof (to convert string to float) 4 | using namespace std; 5 | 6 | int main(int argc, char* argv[]) { 7 | // Check if the correct number of arguments are provided 8 | if (argc != 4) { 9 | cout << "Usage: " << argv[0] << " " << endl; 10 | return 1; // Return error code if arguments are incorrect 11 | } 12 | 13 | // Convert the first and third arguments (numbers) from string to double 14 | double num1 = atof(argv[1]); 15 | double num2 = atof(argv[3]); 16 | 17 | // Get the operator from the second argument 18 | char op = argv[2][0]; 19 | 20 | // Perform the calculation based on the operator 21 | double result; 22 | switch (op) { 23 | case '+': 24 | result = num1 + num2; 25 | break; 26 | case '-': 27 | result = num1 - num2; 28 | break; 29 | case '*': 30 | result = num1 * num2; 31 | break; 32 | case '/': 33 | if (num2 != 0) { 34 | result = num1 / num2; 35 | } else { 36 | cout << "Error: Division by zero!" << endl; 37 | return 1; // Return error code for division by zero 38 | } 39 | break; 40 | default: 41 | cout << "Error: Unsupported operator '" << op << "'!" << endl; 42 | return 1; // Return error code for invalid operator 43 | } 44 | 45 | // Output the result 46 | cout << "Result: " << num1 << " " << op << " " << num2 << " = " << result << endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /C++ Basics/cpp_conditional_statements.cpp: -------------------------------------------------------------------------------- 1 | // conditional_statements.cpp 2 | // Conditional Statements in C++ 3 | 4 | #include 5 | using namespace std; 6 | 7 | int main() { 8 | int num; 9 | 10 | // If, else if, else 11 | cout << "Enter a number: "; 12 | cin >> num; 13 | 14 | if (num > 0) { 15 | cout << num << " is positive." << endl; 16 | } 17 | else if (num < 0) { 18 | cout << num << " is negative." << endl; 19 | } 20 | else { 21 | cout << "The number is zero." << endl; 22 | } 23 | 24 | // Nested conditions 25 | int a = 10, b = 20; 26 | if (a > 0) { 27 | if (b > a) { 28 | cout << "b is greater than a and a is positive." << endl; 29 | } 30 | } 31 | 32 | // Switch case 33 | int choice; 34 | cout << "Choose a number between 1 and 3: "; 35 | cin >> choice; 36 | 37 | switch (choice) { 38 | case 1: 39 | cout << "You chose 1." << endl; 40 | break; 41 | case 2: 42 | cout << "You chose 2." << endl; 43 | break; 44 | case 3: 45 | cout << "You chose 3." << endl; 46 | break; 47 | default: 48 | cout << "Invalid choice!" << endl; 49 | } 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /C++ Basics/cpp_dynamic_memory_allocation.cpp: -------------------------------------------------------------------------------- 1 | // dynamic_memory_allocation.cpp 2 | // Dynamic Memory Allocation in C++ 3 | 4 | #include 5 | #include // For smart pointers 6 | using namespace std; 7 | 8 | int main() { 9 | // Dynamic memory allocation using new and delete 10 | int* ptr = new int; // Allocate memory for an integer 11 | *ptr = 42; // Assign value 12 | cout << "Value allocated dynamically: " << *ptr << endl; 13 | delete ptr; // Free the allocated memory 14 | 15 | // Dynamic arrays 16 | int size; 17 | cout << "Enter size of the array: "; 18 | cin >> size; 19 | 20 | int* dynamicArray = new int[size]; // Allocate dynamic array 21 | for (int i = 0; i < size; i++) { 22 | dynamicArray[i] = i + 1; // Assign values 23 | } 24 | 25 | cout << "Dynamic array elements: "; 26 | for (int i = 0; i < size; i++) { 27 | cout << dynamicArray[i] << " "; // Accessing dynamic array elements 28 | } 29 | cout << endl; 30 | 31 | delete[] dynamicArray; // Free the allocated memory for the array 32 | 33 | // Smart pointers 34 | // Using unique_ptr 35 | unique_ptr uniquePtr(new int(100)); // Allocate using unique_ptr 36 | cout << "Value in unique_ptr: " << *uniquePtr << endl; 37 | 38 | // Using shared_ptr 39 | shared_ptr sharedPtr1(new int(200)); // Allocate using shared_ptr 40 | { 41 | shared_ptr sharedPtr2 = sharedPtr1; // Shared ownership 42 | cout << "Value in shared_ptr: " << *sharedPtr2 << endl; 43 | cout << "Shared reference count: " << sharedPtr2.use_count() << endl; 44 | } 45 | cout << "Shared reference count after sharedPtr2 goes out of scope: " << sharedPtr1.use_count() << endl; 46 | 47 | // Using weak_ptr 48 | weak_ptr weakPtr = sharedPtr1; // Create a weak_ptr from shared_ptr 49 | cout << "Is weak_ptr expired? " << (weakPtr.expired() ? "Yes" : "No") << endl; 50 | 51 | if (auto sharedPtr3 = weakPtr.lock()) { // Lock to get a shared_ptr 52 | cout << "Value in weak_ptr: " << *sharedPtr3 << endl; 53 | } else { 54 | cout << "weak_ptr is expired!" << endl; 55 | } 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /C++ Basics/cpp_file_handling.cpp: -------------------------------------------------------------------------------- 1 | // file_handling.cpp 2 | // File Handling in C++ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int main() { 11 | // File streams: ifstream for reading, ofstream for writing, fstream for both 12 | string filename = "example.txt"; 13 | 14 | // Writing to a file 15 | ofstream outFile(filename); 16 | if (!outFile) { // Error handling 17 | cerr << "Error opening file for writing!" << endl; 18 | return 1; 19 | } 20 | 21 | outFile << "Hello, World!" << endl; // Writing to the file 22 | outFile << "This is a test file for file handling in C++." << endl; 23 | outFile.close(); // Close the file after writing 24 | 25 | // Reading from a file 26 | ifstream inFile(filename); 27 | if (!inFile) { // Error handling 28 | cerr << "Error opening file for reading!" << endl; 29 | return 1; 30 | } 31 | 32 | string line; 33 | cout << "Contents of the file:" << endl; 34 | while (getline(inFile, line)) { // Reading line by line 35 | cout << line << endl; 36 | } 37 | inFile.close(); // Close the file after reading 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /C++ Basics/cpp_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | // Function Declaration and Definition 6 | // Syntax: return_type function_name(parameters) { function_body; } 7 | 8 | // 1. Simple function with no parameters and no return value 9 | void sayHello() { 10 | cout << "Hello, World!" << endl; 11 | } 12 | 13 | // 2. Function with parameters 14 | void greetUser(string name) { 15 | cout << "Hello, " << name << "!" << endl; 16 | } 17 | 18 | // 3. Function with return value 19 | int add(int a, int b) { 20 | return a + b; 21 | } 22 | 23 | // 4. Function with default parameters 24 | void displayInfo(string name = "User", int age = 18) { 25 | cout << "Name: " << name << ", Age: " << age << endl; 26 | } 27 | 28 | // 5. Function Overloading - Same function name, but different parameters 29 | int multiply(int a, int b) { 30 | return a * b; 31 | } 32 | 33 | double multiply(double a, double b) { 34 | return a * b; 35 | } 36 | 37 | // 6. Pass by Value - The original value is not modified 38 | void incrementValue(int num) { 39 | num++; 40 | cout << "Inside function: " << num << endl; // Shows incremented value 41 | } 42 | 43 | // 7. Pass by Reference - The original value is modified 44 | void incrementReference(int &num) { 45 | num++; 46 | cout << "Inside function: " << num << endl; // Shows incremented value 47 | } 48 | 49 | // 8. Recursive Function - Function that calls itself 50 | int factorial(int n) { 51 | if (n <= 1) { 52 | return 1; // Base case 53 | } 54 | return n * factorial(n - 1); // Recursive call 55 | } 56 | 57 | // Main function 58 | int main() { 59 | // 1. Calling a simple function 60 | sayHello(); 61 | 62 | // 2. Function with parameters 63 | greetUser("Alice"); 64 | 65 | // 3. Function with return value 66 | int sum = add(5, 7); 67 | cout << "Sum: " << sum << endl; 68 | 69 | // 4. Function with default parameters 70 | displayInfo(); // Uses default values 71 | displayInfo("Bob", 25); // Overrides default values 72 | 73 | // 5. Function Overloading 74 | cout << "Multiplication (int): " << multiply(3, 4) << endl; 75 | cout << "Multiplication (double): " << multiply(2.5, 4.5) << endl; 76 | 77 | // 6. Pass by Value 78 | int number = 10; 79 | incrementValue(number); 80 | cout << "After function call (pass by value): " << number << endl; // Original value remains unchanged 81 | 82 | // 7. Pass by Reference 83 | incrementReference(number); 84 | cout << "After function call (pass by reference): " << number << endl; // Value is changed 85 | 86 | // 8. Recursive Function 87 | int fact = factorial(5); 88 | cout << "Factorial of 5: " << fact << endl; 89 | 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /C++ Basics/cpp_loops.cpp: -------------------------------------------------------------------------------- 1 | 2 | // loops.cpp 3 | // Loops in C++ 4 | 5 | #include 6 | using namespace std; 7 | 8 | int main() { 9 | // For loop 10 | cout << "For loop (print numbers from 1 to 5):" << endl; 11 | for (int i = 1; i <= 5; i++) { 12 | cout << i << " "; 13 | } 14 | cout << endl; 15 | 16 | // While loop 17 | cout << "While loop (print numbers from 1 to 5):" << endl; 18 | int j = 1; 19 | while (j <= 5) { 20 | cout << j << " "; 21 | j++; 22 | } 23 | cout << endl; 24 | 25 | // Do-while loop 26 | cout << "Do-while loop (print numbers from 1 to 5):" << endl; 27 | int k = 1; 28 | do { 29 | cout << k << " "; 30 | k++; 31 | } while (k <= 5); 32 | cout << endl; 33 | 34 | // Break and continue 35 | cout << "Break and continue example:" << endl; 36 | for (int x = 1; x <= 10; x++) { 37 | if (x == 6) { 38 | cout << "\nBreaking at " << x << endl; 39 | break; // Exits the loop when x == 6 40 | } 41 | if (x % 2 == 0) { 42 | continue; // Skips the rest of the loop when x is even 43 | } 44 | cout << x << " "; // Only odd numbers will be printed 45 | } 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /C++ Basics/cpp_pointers.cpp: -------------------------------------------------------------------------------- 1 | // pointers.cpp 2 | // Understanding Pointers in C++ 3 | 4 | #include 5 | using namespace std; 6 | 7 | void functionWithPointer(int* ptr) { 8 | cout << "Value at pointer: " << *ptr << endl; // Dereferencing the pointer 9 | } 10 | 11 | int main() { 12 | // Introduction to pointers 13 | int var = 42; // An integer variable 14 | int* ptr = &var; // Pointer declaration and initialization 15 | cout << "Value of var: " << var << endl; 16 | cout << "Address of var: " << &var << endl; 17 | cout << "Value at ptr: " << *ptr << endl; // Dereferencing 18 | 19 | // Pointer arithmetic 20 | int arr[3] = {1, 2, 3}; // An array 21 | int* arrPtr = arr; // Pointer to the first element of the array 22 | 23 | cout << "Array elements using pointer arithmetic:" << endl; 24 | for (int i = 0; i < 3; i++) { 25 | cout << *(arrPtr + i) << " "; // Accessing array elements using pointer arithmetic 26 | } 27 | cout << endl; 28 | 29 | // Pointers and arrays 30 | cout << "Accessing array elements directly:" << endl; 31 | for (int i = 0; i < 3; i++) { 32 | cout << arr[i] << " "; // Accessing array elements directly 33 | } 34 | cout << endl; 35 | 36 | // Pointers to functions 37 | void (*funcPtr)(int*) = functionWithPointer; // Pointer to a function 38 | funcPtr(ptr); // Calling the function using pointer to function 39 | 40 | // Pointers to pointers (double pointers) 41 | int** doublePtr = &ptr; // Pointer to a pointer 42 | cout << "Value at doublePtr: " << **doublePtr << endl; // Dereferencing twice 43 | 44 | // Null pointers and nullptr 45 | int* nullPtr = nullptr; // C++11 way to initialize a null pointer 46 | if (nullPtr == nullptr) { 47 | cout << "nullPtr is null." << endl; 48 | } 49 | 50 | // const pointers and pointer const 51 | int value = 100; 52 | const int* constPtr = &value; // Pointer to const int 53 | cout << "Value pointed by constPtr: " << *constPtr << endl; 54 | 55 | // const pointer 56 | int* const constPointer = &var; // const pointer 57 | *constPointer = 50; // Allowed: changing the value of var 58 | cout << "Updated var: " << var << endl; 59 | 60 | // const pointer (to const) 61 | const int* const constPointerToConst = &value; // const pointer to const 62 | // *constPointerToConst = 200; // Error: cannot change value through a const pointer to const 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /C++ Basics/cpp_preprocessor_directives.cpp: -------------------------------------------------------------------------------- 1 | // preprocessor_directives.cpp 2 | // Preprocessor Directives in C++ 3 | 4 | #include 5 | using namespace std; 6 | 7 | // Macro definition using #define 8 | #define SQUARE(x) ((x) * (x)) // Macro to calculate the square of a number 9 | 10 | // Conditional compilation 11 | #define DEBUG // Uncomment to enable debug mode 12 | 13 | int main() { 14 | // Using #include to include the iostream header 15 | cout << "Preprocessor Directives Example" << endl; 16 | 17 | // Using the defined macro 18 | int num = 5; 19 | cout << "Square of " << num << " is " << SQUARE(num) << endl; 20 | 21 | // Conditional compilation 22 | #ifdef DEBUG 23 | cout << "Debug mode is enabled." << endl; // This will be included if DEBUG is defined 24 | #else 25 | cout << "Debug mode is disabled." << endl; // This will be included if DEBUG is not defined 26 | #endif 27 | 28 | // Using #pragma directives 29 | #pragma message("This is a message from the preprocessor.") // Display a message during compilation 30 | #pragma once // Ensure the header file is included only once (useful in header files) 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /C++ Basics/cpp_strings.cpp: -------------------------------------------------------------------------------- 1 | // strings.cpp 2 | // Working with Strings in C++ 3 | 4 | #include 5 | #include // For C-style string functions 6 | #include // For std::string 7 | using namespace std; 8 | 9 | int main() { 10 | 11 | // Character arrays (C-strings) 12 | char cstr[20]; // Declare a C-string (character array) 13 | strcpy(cstr, "Hello C++!"); // Copy a string into the C-string 14 | cout << "C-string: " << cstr << endl; 15 | 16 | // Introduction to std::string 17 | string cppStr = "Hello, std::string!"; // Declare and initialize a C++ string 18 | cout << "C++ string: " << cppStr << endl; 19 | 20 | // String functions 21 | // Length of the string 22 | cout << "Length of C++ string: " << cppStr.length() << endl; 23 | 24 | // Substring 25 | string subStr = cppStr.substr(0, 5); // Extract substring from index 0 to 4 26 | cout << "Substring: " << subStr << endl; 27 | 28 | // Find a substring 29 | size_t pos = cppStr.find("std"); 30 | if (pos != string::npos) { 31 | cout << "'std' found at index: " << pos << endl; 32 | } else { 33 | cout << "'std' not found!" << endl; 34 | } 35 | 36 | // Concatenation 37 | string concatenatedStr = cppStr + " Concatenation example!"; 38 | cout << "Concatenated string: " << concatenatedStr << endl; 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /C++ Basics/cpp_structures_and_unions.cpp: -------------------------------------------------------------------------------- 1 | // structures_and_unions.cpp 2 | // Structures and Unions in C++ 3 | 4 | #include 5 | using namespace std; 6 | 7 | // Defining a structure 8 | struct Point { 9 | int x; 10 | int y; 11 | }; 12 | 13 | // Function that uses a structure 14 | void printPoint(const Point& p) { 15 | cout << "Point(" << p.x << ", " << p.y << ")" << endl; 16 | } 17 | 18 | // Defining a union 19 | union Data { 20 | int intValue; 21 | float floatValue; 22 | char charValue; 23 | }; 24 | 25 | // Enum definition 26 | enum Color { 27 | RED, 28 | GREEN, 29 | BLUE 30 | }; 31 | 32 | // Enum class definition (C++11) 33 | enum class Direction { 34 | NORTH, 35 | SOUTH, 36 | EAST, 37 | WEST 38 | }; 39 | 40 | int main() { 41 | // Using structures 42 | Point p1; // Declare a Point structure 43 | p1.x = 10; // Assign values 44 | p1.y = 20; 45 | printPoint(p1); // Call function using structure 46 | 47 | // Using unions 48 | Data data; // Declare a union 49 | data.intValue = 5; // Assign integer value 50 | cout << "Union intValue: " << data.intValue << endl; 51 | 52 | data.floatValue = 3.14; // Assign float value (overwrites intValue) 53 | cout << "Union floatValue: " << data.floatValue << endl; 54 | 55 | // Note: Accessing intValue after assigning floatValue leads to undefined behavior 56 | // cout << "Union intValue after float assignment: " << data.intValue << endl; // Undefined behavior 57 | 58 | // Using enum 59 | Color myColor = GREEN; // Assign enum value 60 | if (myColor == GREEN) { 61 | cout << "The color is GREEN." << endl; 62 | } 63 | 64 | // Using enum class 65 | Direction myDirection = Direction::NORTH; // Assign enum class value 66 | if (myDirection == Direction::NORTH) { 67 | cout << "The direction is NORTH." << endl; 68 | } 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /C++ Basics/cpp_variable_scope_lifetime.cpp: -------------------------------------------------------------------------------- 1 | // cpp_variable_scope_lifetime.cpp 2 | // This program demonstrates the concepts of variable scope and lifetime in C++. 3 | 4 | #include 5 | 6 | using namespace std; 7 | 8 | /* 9 | Variable Scope: 10 | Scope defines the region of the program where a variable is accessible. 11 | C++ has several types of scopes: 12 | 1. Block Scope 13 | 2. Function Scope 14 | 3. Global Scope 15 | 4. Class Scope 16 | 17 | Variable Lifetime: 18 | Lifetime refers to the duration for which a variable exists in memory. 19 | Different storage durations in C++ determine the lifetime of variables: 20 | 1. Automatic Storage Duration 21 | 2. Static Storage Duration 22 | 3. Dynamic Storage Duration 23 | */ 24 | 25 | // 1. Block Scope 26 | void blockScopeExample() { 27 | cout << "Entering blockScopeExample()\n"; 28 | 29 | if (true) { // Start of a new block 30 | int x = 10; // 'x' has block scope 31 | cout << "Inside block: x = " << x << endl; 32 | } // 'x' is destroyed here 33 | 34 | // Uncommenting the next line would cause a compilation error because 'x' is out of scope 35 | // cout << x; 36 | 37 | cout << "Exiting blockScopeExample()\n\n"; 38 | } 39 | 40 | // 2. Function Scope 41 | int globalVar = 100; // Global variable 42 | 43 | void functionScopeExample() { 44 | cout << "Entering functionScopeExample()\n"; 45 | // 'globalVar' is accessible here 46 | cout << "Global variable: globalVar = " << globalVar << endl; 47 | cout << "Exiting functionScopeExample()\n\n"; 48 | } 49 | 50 | // 3. Global Scope 51 | int globalScopeVar = 200; // Accessible throughout the file after its declaration 52 | 53 | void globalScopeAccess() { 54 | cout << "Accessing globalScopeVar from globalScopeAccess(): " << globalScopeVar << endl; 55 | } 56 | 57 | // 4. Class Scope 58 | class MyClass { 59 | public: 60 | int memberVar; 61 | 62 | MyClass(int val) : memberVar(val) { 63 | cout << "MyClass constructor called. memberVar = " << memberVar << endl; 64 | } 65 | 66 | void display() { 67 | cout << "MyClass memberVar: " << memberVar << endl; 68 | } 69 | }; 70 | 71 | // Variable Lifetime Examples 72 | 73 | // Automatic Storage Duration 74 | void automaticLifetime() { 75 | cout << "Entering automaticLifetime()\n"; 76 | int autoVar = 300; // 'autoVar' is created here 77 | cout << "autoVar = " << autoVar << endl; 78 | // 'autoVar' is destroyed when the function returns 79 | cout << "Exiting automaticLifetime()\n\n"; 80 | } 81 | 82 | // Static Storage Duration 83 | void staticLifetime() { 84 | cout << "Entering staticLifetime()\n"; 85 | static int staticVar = 400; // 'staticVar' is initialized only once 86 | cout << "staticVar = " << staticVar << endl; 87 | staticVar++; 88 | cout << "staticVar after increment = " << staticVar << endl; 89 | // 'staticVar' exists until the program ends 90 | cout << "Exiting staticLifetime()\n\n"; 91 | } 92 | 93 | // Dynamic Storage Duration 94 | void dynamicLifetime() { 95 | cout << "Entering dynamicLifetime()\n"; 96 | int* dynVar = new int(500); // 'dynVar' points to dynamically allocated memory 97 | cout << "*dynVar = " << *dynVar << endl; 98 | delete dynVar; // Memory is freed here 99 | // 'dynVar' pointer is destroyed when it goes out of scope, but the allocated memory must be freed manually 100 | cout << "Exiting dynamicLifetime()\n\n"; 101 | } 102 | 103 | int main() { 104 | cout << "Variable Scope and Lifetime Demonstration in C++\n\n"; 105 | 106 | // Demonstrate Block Scope 107 | blockScopeExample(); 108 | 109 | // Demonstrate Function Scope (accessing global variable) 110 | functionScopeExample(); 111 | 112 | // Demonstrate Global Scope 113 | globalScopeAccess(); 114 | 115 | // Demonstrate Class Scope 116 | MyClass obj(600); 117 | obj.display(); 118 | 119 | // Demonstrate Variable Lifetime 120 | automaticLifetime(); 121 | staticLifetime(); 122 | staticLifetime(); // Static variable retains its value between calls 123 | dynamicLifetime(); 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /Casting in C++/casting_cpp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Base { 4 | public: 5 | virtual void Show() { std::cout << "Base Class!" << std::endl; } 6 | }; 7 | class Derived : public Base { 8 | public: 9 | void Show() override { std::cout << "Derived Class!" << std::endl; } 10 | }; 11 | 12 | int main() 13 | { 14 | // Implicit casting 15 | int i = 10; 16 | double di = i; 17 | std::cout << "Implicit casting : " << di << std::endl; 18 | 19 | // C-style casting 20 | double pi = 3.14; 21 | int intPi = (int)pi; 22 | std::cout << "C-style cast : " << intPi << std::endl; 23 | 24 | // Static cast : 25 | int a = 65; 26 | double d = static_cast(a); 27 | std::cout << "Static cast : " << d << std::endl; 28 | 29 | // Dynamic cast : 30 | // Safely casts pointers or references in a class hierarchy. It performs a runtime check, typically used for polymorphism. 31 | Base* base = new Base(); 32 | Derived* derived = dynamic_cast(base); 33 | if(derived) 34 | derived->Show(); 35 | 36 | // Reinterpret cast 37 | // Converts between unrelated pointer types with no safety checks. It's used in low-level operations. 38 | int n = 1; 39 | char* c = reinterpret_cast(&n); 40 | std::cout << "Reinterpret cast : " << static_cast(*c) << std::endl; 41 | 42 | return 0; 43 | } 44 | 45 | 46 | -------------------------------------------------------------------------------- /Cpp_cheatsheet/C++CheatSheet - V1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helyousfi/cpp-concepts/f0f0730fb5fe20412c21ce6c6ae04d8d94d33e5e/Cpp_cheatsheet/C++CheatSheet - V1.pdf -------------------------------------------------------------------------------- /CreateDLL/MyDLL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" { 4 | __declspec(dllexport) void hello() { // mark the function as exportable 5 | std::cout << "Hello World!" << std::endl; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CreateDLL/MyDLL.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helyousfi/cpp-concepts/f0f0730fb5fe20412c21ce6c6ae04d8d94d33e5e/CreateDLL/MyDLL.dll -------------------------------------------------------------------------------- /CreateDLL/MyDLL.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MYDLL_h 2 | #define MYDLL_h 3 | 4 | extern "C" { 5 | void hello(); 6 | } 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /CreateDLL/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include"MyDLL.hpp" 3 | 4 | int main() { 5 | hello(); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /CreateDLL/readme.md: -------------------------------------------------------------------------------- 1 | # Compile DLL with MinGW 2 | - to compile the DLL : g++ -shared -o MyDLL.dll MyDLL.cpp 3 | - to generate exe : g++ -o MyApp main.cpp -L. -lMyDLL 4 | 5 | # Understanding DLLs and Static Libraries 6 | 7 | ## Static Library 8 | 9 | - **Definition:** 10 | A static library is a collection of object files that are linked directly into your executable at compile time. The library’s code becomes part of the final executable. 11 | 12 | - **Advantages:** 13 | - **Single File Deployment:** No need to distribute separate library files. 14 | - **Simplicity:** Everything is included in one file, making deployment easier. 15 | 16 | - **Disadvantages:** 17 | - **Increased Executable Size:** The final executable file is larger because it includes the library code. 18 | - **Update Complexity:** Updating the library requires recompiling the executable if the library changes. 19 | 20 | - **Use Case Example:** 21 | - **Static Library:** Use when developing a small utility tool where you prefer to have everything bundled together, and you don’t expect frequent updates to the library. For instance, a standalone calculator application with built-in functions. 22 | 23 | ## DLL (Dynamic Link Library) 24 | 25 | - **Definition:** 26 | A DLL is a separate file that contains code and data used by multiple programs. It is loaded and linked at runtime, rather than at compile time. 27 | 28 | - **Advantages:** 29 | - **Reduced Executable Size:** The main executable file remains smaller as the library code is separate. 30 | - **Update Flexibility:** Allows updates to the library without needing to recompile the application. 31 | - **Shared Use:** Can be used by multiple applications, saving memory and disk space. 32 | 33 | - **Disadvantages:** 34 | - **Version Management:** Requires careful management of DLL versions and dependencies. 35 | - **Deployment Complexity:** Involves distributing multiple files, making deployment slightly more complex. 36 | 37 | - **Use Case Example:** 38 | - **DLL:** Ideal for larger applications or systems with shared components that need independent updates. For example, a web browser that uses plugins (DLLs) which can be updated without affecting the main browser executable. 39 | 40 | ## Summary 41 | 42 | - **Static Library:** Best suited for simple, standalone applications where you want all code bundled into a single file and don’t anticipate frequent updates. 43 | - **DLL:** Ideal for larger applications or systems with components that may be updated independently, allowing for shared code across multiple programs. 44 | -------------------------------------------------------------------------------- /Debugging/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello world" << std::endl; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /Debugging/readme.md: -------------------------------------------------------------------------------- 1 | What is Debug Mode? 2 | When you compile a program, you can choose different modes which affect how the compiler optimizes and manages the code. Debug mode is one of these options. Here's what it typically involves: 3 | 4 | - Debugging Information: In debug mode, the compiler includes additional information in the executable that helps with debugging. This includes information about the source code lines, variable names, and other details that make it easier to trace and debug issues. 5 | 6 | - No Optimization: The compiler does not perform aggressive optimizations in debug mode. Optimization can change the way code executes and can make debugging more difficult, so it’s generally turned off. 7 | 8 | - Error Checking: Debug mode often includes additional runtime checks that can help catch errors that might be harder to find otherwise. For example, it might help detect buffer overflows or uninitialized variables. 9 | 10 | 11 | # Debugging with GDB and MinGW 12 | 13 | This guide explains how to use GDB (GNU Debugger) with MinGW for debugging C++ programs on Windows. 14 | 15 | ## Compiling Your Program with Debug Information 16 | 17 | To enable debugging, you need to compile your program with the `-g` flag. This includes debugging information in the executable. 18 | 19 | ``` 20 | g++ -g -o myprogram myprogram.cpp 21 | ``` 22 | Here: 23 | 24 | - -g adds debugging information. 25 | - -o myprogram specifies the name of the output executable. 26 | 27 | ## Starting GDB 28 | Navigate to the directory containing your compiled program and start GDB with: 29 | ``` 30 | gdb myprogram 31 | ``` 32 | Add a break point: 33 | ``` 34 | break main 35 | ``` 36 | To run the program : 37 | ``` 38 | run 39 | ``` 40 | To step into next line : 41 | ``` 42 | next 43 | ``` 44 | Then to show the assembly : 45 | ``` 46 | disassemble 47 | ``` 48 | ``` 49 | print *p 50 | ``` 51 | -------------------------------------------------------------------------------- /Labs/01_Digits.cpp: -------------------------------------------------------------------------------- 1 | // A program to calculate sum of digits 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | int number, sum = 0; 8 | // Get the number from user 9 | std::cout << "Enter number : "; 10 | std::cin >> number; 11 | 12 | // Add modulo 10, 100, ... 13 | while(number != 0) 14 | { 15 | sum += number%10; 16 | number = number / 10; 17 | } 18 | std::cout << sum; 19 | } 20 | -------------------------------------------------------------------------------- /Labs/02_fibonacci.cpp: -------------------------------------------------------------------------------- 1 | // Print fibonacci numbers iteratively 2 | // 1, 1, 2, 3, 5, ... 3 | #include 4 | 5 | int main() 6 | { 7 | int a=0, b=1, sum=0; 8 | while(a < 100) 9 | { 10 | sum = a + b; 11 | a = b; 12 | b = sum; 13 | if(b > 100) 14 | break; 15 | std::cout << sum << ' '; 16 | } 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Labs/03_prime.cpp: -------------------------------------------------------------------------------- 1 | // Program to find if a number is prime 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | int number, isPrime = 0; 8 | std::cout << "Enter Number : "; 9 | std::cin >> number; 10 | 11 | for(int k=2; k < number/2; ++k) 12 | { 13 | if(number % k == 0){ 14 | isPrime++; 15 | break; 16 | } 17 | } 18 | if(isPrime != 0) 19 | std::cout << "Number is not prime"; 20 | else 21 | std::cout << "Number is prime"; 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /Labs/04_gcd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int gcd(int x, int y) 5 | { 6 | if(x == 0 || y == 0) 7 | return 0; 8 | if(x == y) 9 | return x; 10 | if(x > y) 11 | return gcd(x-y, y); 12 | if(y > x) 13 | return gcd(x, y-x); 14 | } 15 | 16 | int main() 17 | { 18 | std::cout << gcd(14,10) << std::endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /Labs/05_merging_vectors.cpp: -------------------------------------------------------------------------------- 1 | // Include necessary headers 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define dec_vector std::vector 8 | #define DEACTIVATE 9 | 10 | // Function to print a vector 11 | void print_vec(const dec_vector& vec) 12 | { 13 | for(const int& i : vec) 14 | std::cout << i << ' '; 15 | std::cout << std::endl; 16 | } 17 | 18 | // Function to merge two vectors 19 | void merging(dec_vector& vec1, 20 | dec_vector& vec2, 21 | dec_vector& output) 22 | { 23 | 24 | // Sorting the three vectors 25 | std::sort(vec1.begin(), vec1.end()); 26 | std::sort(vec2.begin(), vec2.end()); 27 | 28 | // Resize output 29 | output.resize(vec1.size() + vec2.size()); 30 | 31 | 32 | // Merging vectors 33 | std::vector::iterator it_vec1 = vec1.begin(); 34 | std::vector::iterator it_vec2 = vec2.begin(); 35 | std::vector::iterator it_output = output.begin(); 36 | 37 | 38 | while(it_vec1 != vec1.end() && it_vec2 != vec2.end()) 39 | { 40 | if(*it_vec1 < *it_vec2){ 41 | *(it_output++) = *it_vec1; 42 | ++it_vec1; 43 | } 44 | else{ 45 | *(it_output++) = *it_vec2; 46 | ++it_vec2; 47 | } 48 | } 49 | 50 | while(it_vec2 != vec2.end()) 51 | *(it_output++) = *(it_vec2++); 52 | while(it_vec1 != vec1.end()) 53 | *(it_output++) = *(it_vec1++); 54 | 55 | } 56 | 57 | int main() 58 | { 59 | dec_vector vec1 = {1, 5, 6, 9, 55, 7, 99}; 60 | dec_vector vec2 = {0, 4, 9, 3, 1, 2}; 61 | dec_vector output; 62 | 63 | merging(vec1, vec2, output); 64 | print_vec(output); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /Labs/06_average_it_vec.cpp: -------------------------------------------------------------------------------- 1 | // Calculating average using vectors and iterators 2 | #include 3 | #include 4 | #include 5 | 6 | // Vector average using iterators 7 | float vec_avg(const std::vector& vec) 8 | { 9 | if(vec.empty()) 10 | throw std::invalid_argument("Vector is empty!"); 11 | 12 | int sum = 0; 13 | // For learning purpose, I don't use auto 14 | std::vector::const_iterator it = vec.cbegin(); // cbegin to deduce automatically iterator type, here it's a const_iterator 15 | while(it != vec.cend()){ 16 | sum += *it; 17 | ++it; 18 | } 19 | // int sum_acc = std::accumulate(vec.begin(), vec.end(), 0); 20 | return static_cast (sum / vec.size()); 21 | } 22 | 23 | int main() 24 | { 25 | std::vector vec = {1, 2, 3, 4, 5}; 26 | float avg = vec_avg(vec); 27 | std::cout << avg; 28 | return 0; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/ATM/atm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | 7 | class atm 8 | { 9 | private: 10 | long int account_No; 11 | string name; 12 | int PIN; 13 | double balance; 14 | string mobile_No; 15 | 16 | public: 17 | void setData(long int account_No_a, string name_a, int PIN_a, double balance_a, string mobile_No_a) 18 | { 19 | account_No = account_No_a; 20 | name = name_a; 21 | PIN = PIN_a; 22 | balance = balance_a; 23 | mobile_No = mobile_No_a; 24 | } 25 | 26 | long int getAccountNo() 27 | { 28 | return account_No; 29 | } 30 | 31 | string getName() 32 | { 33 | return name; 34 | } 35 | 36 | int getPIN() 37 | { 38 | return PIN; 39 | } 40 | 41 | double getBalance() 42 | { 43 | return balance; 44 | } 45 | 46 | string getMobileNo() 47 | { 48 | return mobile_No; 49 | } 50 | 51 | void setMobile(string mob_prev, string mob_new) 52 | { 53 | if (mob_prev == mobile_No) 54 | { 55 | mobile_No = mob_new; 56 | cout << endl << "Sucessfully Updated Mobile no."; 57 | _getch(); 58 | } 59 | 60 | else 61 | { 62 | cout << endl << "Incorrect !!! Old Mobile no"; 63 | _getch(); 64 | } 65 | } 66 | 67 | void cashWithDraw(int amount_a) 68 | { 69 | if (amount_a > 0 && amount_a < balance) 70 | { 71 | balance -= amount_a; 72 | cout << endl << "Please Collect Your Cash"; 73 | cout << endl << "Available Balance :" << balance; 74 | _getch(); 75 | } 76 | 77 | else 78 | { 79 | cout << endl << "Invalid Input or Insufficient Balance"; 80 | _getch(); 81 | } 82 | } 83 | 84 | }; 85 | 86 | int main() 87 | { 88 | int choice = 0, enterPIN; 89 | long int enterAccountNo; 90 | 91 | system("cls"); 92 | 93 | atm user1; 94 | user1.setData(558963, "interrupt101", 2125, 2000, "068558600"); 95 | 96 | 97 | do 98 | { 99 | system("cls"); 100 | 101 | cout << endl << "****Welcome to ATM*****" << endl; 102 | cout << endl << "Enter Your Account No "; 103 | cin >> enterAccountNo; 104 | 105 | cout << endl << "Enter PIN "; 106 | cin >> enterPIN; 107 | 108 | if ((enterAccountNo == user1.getAccountNo()) && (enterPIN == user1.getPIN())) 109 | { 110 | do 111 | { 112 | int amount = 0; 113 | string oldMobileNo, newMobileNo; 114 | 115 | system("cls"); 116 | 117 | cout << endl << "**** Welcome to ATM *****" << endl; 118 | cout << endl << "Select Options "; 119 | cout << endl << "1. Check Balance"; 120 | cout << endl << "2. Cash withdraw"; 121 | cout << endl << "3. Show User Details"; 122 | cout << endl << "4. Update Mobile no."; 123 | cout << endl << "5. Exit" << endl; 124 | cin >> choice; 125 | 126 | switch (choice) 127 | { 128 | case 1: 129 | cout << endl << "Your Bank balance is :" << user1.getBalance(); 130 | _getch(); 131 | break; 132 | 133 | 134 | case 2: 135 | cout << endl << "Enter the amount :"; 136 | cin >> amount; 137 | user1.cashWithDraw(amount); 138 | break; 139 | 140 | 141 | case 3: 142 | cout << endl << "*** User Details are :- "; 143 | cout << endl << "-> Account no :" << user1.getAccountNo(); 144 | cout << endl << "-> Name :" << user1.getName(); 145 | cout << endl << "-> Balance :" << user1.getBalance(); 146 | cout << endl << "-> Mobile No. :" << user1.getMobileNo(); 147 | _getch(); 148 | break; 149 | 150 | 151 | case 4: 152 | cout << endl << "Enter Old Mobile No. "; 153 | cin >> oldMobileNo; 154 | 155 | cout << endl << "Enter New Mobile No. "; 156 | cin >> newMobileNo; 157 | 158 | user1.setMobile(oldMobileNo, newMobileNo); 159 | break; 160 | 161 | 162 | case 5: 163 | exit(0); 164 | 165 | default: 166 | cout << endl << "Enter Valid Data !!!"; 167 | } 168 | 169 | } while (1); 170 | } 171 | 172 | else 173 | { 174 | cout << endl << "User Details are Invalid !!! "; 175 | _getch(); 176 | } 177 | } while (1); 178 | 179 | return 0; 180 | } 181 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Library.h" 3 | 4 | void displayMenu() { 5 | std::cout << "Library Management System\n"; 6 | std::cout << "1. Add Book\n"; 7 | std::cout << "2. Remove Book\n"; 8 | std::cout << "3. Display All Books\n"; 9 | std::cout << "4. Add Member\n"; 10 | std::cout << "5. Remove Member\n"; 11 | std::cout << "6. Display All Members\n"; 12 | std::cout << "7. Borrow Book\n"; 13 | std::cout << "8. Return Book\n"; 14 | std::cout << "9. Exit\n"; 15 | std::cout << "Enter your choice: "; 16 | } 17 | 18 | int main() { 19 | Library library; 20 | int choice; 21 | 22 | do { 23 | displayMenu(); 24 | std::cin >> choice; 25 | 26 | int id; 27 | std::string title, author, publisher, name, email; 28 | 29 | switch (choice) { 30 | case 1: 31 | std::cout << "Enter book ID: "; 32 | std::cin >> id; 33 | std::cout << "Enter title: "; 34 | std::cin.ignore(); 35 | std::getline(std::cin, title); 36 | std::cout << "Enter author: "; 37 | std::getline(std::cin, author); 38 | std::cout << "Enter publisher: "; 39 | std::getline(std::cin, publisher); 40 | library.addBook(Book(id, title, author, publisher)); 41 | break; 42 | 43 | case 2: 44 | std::cout << "Enter book ID: "; 45 | std::cin >> id; 46 | library.removeBook(id); 47 | break; 48 | 49 | case 3: 50 | library.displayAllBooks(); 51 | break; 52 | 53 | case 4: 54 | std::cout << "Enter member ID: "; 55 | std::cin >> id; 56 | std::cout << "Enter name: "; 57 | std::cin.ignore(); 58 | std::getline(std::cin, name); 59 | std::cout << "Enter email: "; 60 | std::getline(std::cin, email); 61 | library.addMember(Member(id, name, email)); 62 | break; 63 | 64 | case 5: 65 | std::cout << "Enter member ID: "; 66 | std::cin >> id; 67 | library.removeMember(id); 68 | break; 69 | 70 | case 6: 71 | library.displayAllMembers(); 72 | break; 73 | 74 | case 7: 75 | int memberID, bookID; 76 | std::cout << "Enter member ID: "; 77 | std::cin >> memberID; 78 | std::cout << "Enter book ID: "; 79 | std::cin >> bookID; 80 | library.borrowBook(memberID, bookID); 81 | break; 82 | 83 | case 8: 84 | std::cout << "Enter member ID: "; 85 | std::cin >> memberID; 86 | std::cout << "Enter book ID: "; 87 | std::cin >> bookID; 88 | library.returnBook(memberID, bookID); 89 | break; 90 | 91 | case 9: 92 | std::cout << "Exiting...\n"; 93 | break; 94 | 95 | default: 96 | std::cout << "Invalid choice. Please try again.\n"; 97 | } 98 | } while (choice != 9); 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/Makefile: -------------------------------------------------------------------------------- 1 | # Compiler 2 | CXX = g++ 3 | 4 | # Compiler flags 5 | CXXFLAGS = -Iheaders -std=c++11 -Wall 6 | 7 | # Source files 8 | SRCS = main.cpp sources/Book.cpp sources/Member.cpp sources/Library.cpp 9 | 10 | # Object files 11 | OBJS = $(SRCS:.cpp=.o) 12 | 13 | # Executable name 14 | TARGET = main 15 | 16 | # Build the executable 17 | $(TARGET): $(OBJS) 18 | $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) 19 | 20 | # Compile source files into object files 21 | %.o: %.cpp 22 | $(CXX) $(CXXFLAGS) -c $< -o $@ 23 | 24 | # Clean up build files 25 | clean: 26 | rm -f $(OBJS) $(TARGET) 27 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/SimpleProject.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | 8 | class Book 9 | { 10 | private: 11 | string title; 12 | string author; 13 | bool available; 14 | 15 | public: 16 | Book(string title_p, string author_p) : title(title_p), author(author_p) {} 17 | string getTitle() const { 18 | return title; 19 | } 20 | string getAuthor() const { 21 | return author; 22 | } 23 | bool isAvailable() const { 24 | return available; 25 | } 26 | void setAvailable(bool availability) 27 | { 28 | available = availability; 29 | } 30 | void getDetails() const { 31 | cout << "Title : " << title 32 | << " Author : " << author 33 | << " Available: "<< available << endl; 34 | } 35 | void setTitle(const string& t) {title = t;} 36 | void setAuthor(const string& a) {author = a;} 37 | 38 | }; 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | class Person 48 | { 49 | protected: 50 | string name; 51 | int id; 52 | public: 53 | Person(string name_p, int id_p) : name(name_p), id(id_p) {} 54 | 55 | // Getters 56 | string getName() const { 57 | return name; 58 | } 59 | int getId() const { 60 | return id; 61 | } 62 | // Setters 63 | void setName(const string& n) { 64 | name = n; 65 | } 66 | void setId(const int& id_p) { 67 | id = id_p; 68 | } 69 | 70 | }; 71 | 72 | 73 | class Admin : public Person 74 | { 75 | public: 76 | Admin(string name, int id) : Person(name, id) {} 77 | 78 | void manageBooks() { 79 | cout << "Managing books ..." << endl; 80 | } 81 | 82 | void manageMembers() { 83 | cout << "Managing Members ..." << endl; 84 | } 85 | 86 | }; 87 | 88 | class Member : public Person 89 | { 90 | public: 91 | Member(string name, int id) : Person(name, id) {} 92 | 93 | void borrowBook(Book &book) 94 | { 95 | if(book.isAvailable()) 96 | { 97 | cout << name << " borrowed the book : " 98 | << book.getTitle() << endl; 99 | book.setAvailable(false); 100 | } 101 | else{ 102 | cout << "Book is currently unavailable!" << endl; 103 | } 104 | } 105 | 106 | void returnBook(Book &book) 107 | { 108 | cout << name << " returned the book: " << book.getTitle() << endl; 109 | book.setAvailable(true); 110 | } 111 | 112 | }; 113 | 114 | 115 | class Library 116 | { 117 | private: 118 | vector books; 119 | vector members; 120 | 121 | public: 122 | void addBook(const Book& book) 123 | { 124 | books.push_back(book); 125 | cout << "Book added to library: " << book.getTitle() << endl; 126 | } 127 | 128 | void removeBook(const string& title) 129 | { 130 | for(auto it = books.begin(); it != books.end(); ++it) 131 | { 132 | if(it->getTitle() == title) 133 | { 134 | books.erase(it); 135 | cout << "Book removed from the library: " << title << endl; 136 | return; 137 | } 138 | } 139 | cout << "Book not found!" << endl; 140 | } 141 | 142 | void addMember(const Member& member) 143 | { 144 | members.push_back(member); 145 | cout << "Member added: " << member.getName() << endl; 146 | } 147 | 148 | void issueBook(const string& title, Member& member) 149 | { 150 | for(auto &book : books) 151 | { 152 | if(book.getTitle() == title && book.isAvailable()) 153 | { 154 | member.borrowBook(book); 155 | return; 156 | } 157 | } 158 | cout << "Book not available or not found" << endl; 159 | } 160 | 161 | void returnBook(const string& title, Member& member) 162 | { 163 | for(auto &book : books) 164 | { 165 | if(book.getTitle() == title) 166 | { 167 | member.returnBook(book); 168 | return; 169 | } 170 | } 171 | cout << "Book not found in the library" << endl; 172 | } 173 | 174 | void displayBooks() const { 175 | cout << "Books in the library: " << endl; 176 | for(const auto& book : books) 177 | { 178 | book.getDetails(); 179 | } 180 | 181 | } 182 | }; 183 | 184 | 185 | 186 | int main() 187 | { 188 | Library library; 189 | 190 | Book book1("Moqadimat Ibn Khaldoun", "Ibn Khaldoon"); 191 | Book book2("C++ programming language", "bjarne stroustrup"); 192 | 193 | Admin admin("Mohamed", 101); 194 | Member member("Ahmed", 102); 195 | 196 | library.addBook(book1); 197 | library.addBook(book2); 198 | 199 | library.displayBooks(); 200 | 201 | library.addMember(member); 202 | library.issueBook("C++ programming language", member); 203 | library.issueBook("C++ programming language", member); 204 | library.returnBook("C++ programming language", member); 205 | 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/headers/Book.h: -------------------------------------------------------------------------------- 1 | #ifndef BOOK_H 2 | #define BOOK_H 3 | 4 | #include 5 | 6 | class Book { 7 | private: 8 | int bookID; 9 | std::string title; 10 | std::string author; 11 | std::string publisher; 12 | bool isBorrowed; 13 | 14 | public: 15 | Book(int id, std::string t, std::string a, std::string p); 16 | 17 | void displayBookInfo() const; 18 | void borrowBook(); 19 | void returnBook(); 20 | 21 | int getBookID() const; 22 | bool getBorrowedStatus() const; 23 | }; 24 | 25 | #endif // BOOK_H 26 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/headers/Library.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRARY_H 2 | #define LIBRARY_H 3 | 4 | #include 5 | #include "Book.h" 6 | #include "Member.h" 7 | 8 | class Library { 9 | private: 10 | std::vector books; 11 | std::vector members; 12 | 13 | public: 14 | void addBook(const Book& book); 15 | void removeBook(int bookID); 16 | 17 | void addMember(const Member& member); 18 | void removeMember(int memberID); 19 | 20 | void displayAllBooks() const; 21 | void displayAllMembers() const; 22 | 23 | void borrowBook(int memberID, int bookID); 24 | void returnBook(int memberID, int bookID); 25 | }; 26 | 27 | #endif // LIBRARY_H 28 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/headers/Member.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMBER_H 2 | #define MEMBER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Member { 9 | private: 10 | int memberID; 11 | std::string name; 12 | std::string email; 13 | std::set borrowedBooks; 14 | 15 | public: 16 | Member(int id, std::string n, std::string e); 17 | 18 | void displayMemberInfo() const; 19 | void borrowBook(int bookID); 20 | void returnBook(int bookID); 21 | 22 | int getMemberID() const; 23 | std::set getBorrowedBooks() const; 24 | }; 25 | 26 | #endif // MEMBER_H 27 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/readme.md: -------------------------------------------------------------------------------- 1 | This is a very simple management system project (To brush up on OOP & UML) 2 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/sources/Book.cpp: -------------------------------------------------------------------------------- 1 | #include "Book.h" 2 | #include 3 | 4 | Book::Book(int id, std::string t, std::string a, std::string p) 5 | : bookID(id), title(t), author(a), publisher(p), isBorrowed(false) {} 6 | 7 | void Book::displayBookInfo() const{ 8 | std::cout << "Book ID: " << bookID << "\nTitle: " << title 9 | << "\nAuthor: " << author << "\nPublisher: " << publisher 10 | << "\nBorrowed: " << (isBorrowed ? "Yes" : "No") << std::endl; 11 | } 12 | 13 | void Book::borrowBook() { 14 | if (!isBorrowed) { 15 | isBorrowed = true; 16 | std::cout << "Book borrowed successfully." << std::endl; 17 | } else { 18 | std::cout << "Book is already borrowed." << std::endl; 19 | } 20 | } 21 | 22 | void Book::returnBook() { 23 | if (isBorrowed) { 24 | isBorrowed = false; 25 | std::cout << "Book returned successfully." << std::endl; 26 | } else { 27 | std::cout << "Book was not borrowed." << std::endl; 28 | } 29 | } 30 | 31 | int Book::getBookID() const { return bookID; } 32 | 33 | bool Book::getBorrowedStatus() const { return isBorrowed; } 34 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/sources/Library.cpp: -------------------------------------------------------------------------------- 1 | #include "Library.h" 2 | #include 3 | 4 | void Library::addBook(const Book& book) { 5 | books.push_back(book); 6 | std::cout << "Book added successfully." << std::endl; 7 | } 8 | 9 | void Library::removeBook(int bookID) { 10 | for (auto it = books.begin(); it != books.end(); ++it) { 11 | if (it->getBookID() == bookID) { 12 | books.erase(it); 13 | std::cout << "Book removed successfully." << std::endl; 14 | return; 15 | } 16 | } 17 | std::cout << "Book not found." << std::endl; 18 | } 19 | 20 | void Library::addMember(const Member& member) { 21 | members.push_back(member); 22 | std::cout << "Member added successfully." << std::endl; 23 | } 24 | 25 | void Library::removeMember(int memberID) { 26 | for (auto it = members.begin(); it != members.end(); ++it) { 27 | if (it->getMemberID() == memberID) { 28 | members.erase(it); 29 | std::cout << "Member removed successfully." << std::endl; 30 | return; 31 | } 32 | } 33 | std::cout << "Member not found." << std::endl; 34 | } 35 | 36 | void Library::displayAllBooks() const { 37 | for (const auto& book : books) { 38 | book.displayBookInfo(); 39 | std::cout << "-------------------" << std::endl; 40 | } 41 | } 42 | 43 | void Library::displayAllMembers() const { 44 | for (const auto& member : members) { 45 | member.displayMemberInfo(); 46 | std::cout << "-------------------" << std::endl; 47 | } 48 | } 49 | 50 | void Library::borrowBook(int memberID, int bookID) { 51 | for (auto& book : books) { 52 | if (book.getBookID() == bookID && !book.getBorrowedStatus()) { 53 | for (auto& member : members) { 54 | if (member.getMemberID() == memberID) { 55 | book.borrowBook(); 56 | member.borrowBook(bookID); 57 | return; 58 | } 59 | } 60 | std::cout << "Member not found." << std::endl; 61 | return; 62 | } 63 | } 64 | std::cout << "Book not available for borrowing." << std::endl; 65 | } 66 | 67 | void Library::returnBook(int memberID, int bookID) { 68 | for (auto& book : books) { 69 | if (book.getBookID() == bookID && book.getBorrowedStatus()) { 70 | for (auto& member : members) { 71 | if (member.getMemberID() == memberID) { 72 | book.returnBook(); 73 | member.returnBook(bookID); 74 | return; 75 | } 76 | } 77 | std::cout << "Member not found." << std::endl; 78 | return; 79 | } 80 | } 81 | std::cout << "Book not borrowed." << std::endl; 82 | } 83 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/sources/Member.cpp: -------------------------------------------------------------------------------- 1 | #include "Member.h" 2 | #include 3 | #include 4 | 5 | Member::Member(int id, std::string n, std::string e) 6 | : memberID(id), name(n), email(e) {} 7 | 8 | void Member::displayMemberInfo() const { 9 | std::cout << "Member ID: " << memberID << "\nName: " << name 10 | << "\nEmail: " << email << std::endl; 11 | } 12 | 13 | void Member::borrowBook(int bookID) { 14 | borrowedBooks.insert(bookID); 15 | std::cout << "Book borrowed successfully." << std::endl; 16 | } 17 | 18 | void Member::returnBook(int bookID) { 19 | auto it = std::find(borrowedBooks.begin(), borrowedBooks.end(), bookID); 20 | if (it != borrowedBooks.end()) { 21 | borrowedBooks.erase(it); 22 | std::cout << "Book returned successfully." << std::endl; 23 | } else { 24 | std::cout << "Book not found in borrowed list." << std::endl; 25 | } 26 | } 27 | 28 | int Member::getMemberID() const { return memberID; } 29 | 30 | std::set Member::getBorrowedBooks() const { return borrowedBooks; } 31 | -------------------------------------------------------------------------------- /OOP Projects/LibraryManagement/uml.drawio: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helyousfi/cpp-concepts/f0f0730fb5fe20412c21ce6c6ae04d8d94d33e5e/OOP Projects/LibraryManagement/uml.drawio -------------------------------------------------------------------------------- /Object Oriented Programming/move_semantics.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | What is a Move Constructor? 3 | In C++, a move constructor is a special constructor used to "move" resources from one object to another, 4 | rather than copying them. This is particularly useful for optimizing performance by avoiding unnecessary 5 | deep copies, especially for objects managing dynamic resources like memory, file handles, 6 | or network connections. 7 | 8 | Why Do We Need a Move Constructor? 9 | When you pass objects around in your program (like returning an object from a function or passing it 10 | to a function), the default behavior involves copying the object, which can be expensive if the object 11 | manages resources like large arrays or other dynamic memory. 12 | */ 13 | 14 | #include 15 | #include // For std::move 16 | 17 | class MyClass { 18 | private: 19 | int* data; 20 | public: 21 | // Constructor 22 | MyClass(int value) { 23 | data = new int(value); 24 | std::cout << "Constructor called\n"; 25 | } 26 | 27 | // Move Constructor 28 | MyClass(MyClass&& other) noexcept // noexcept : doesn't throw exception (good for optimizations) 29 | : data(other.data) { 30 | other.data = nullptr; // Nullify the source pointer 31 | std::cout << "Move Constructor called\n"; 32 | } 33 | 34 | // Destructor 35 | ~MyClass() { 36 | delete data; 37 | std::cout << "Destructor called\n"; 38 | } 39 | 40 | // Copy Constructor (disabled) 41 | MyClass(const MyClass& other) = delete; 42 | 43 | // Copy Assignment Operator (disabled) 44 | MyClass& operator=(const MyClass& other) = delete; 45 | 46 | // Move Assignment Operator 47 | MyClass& operator=(MyClass&& other) noexcept { 48 | if (this != &other) { 49 | delete data; // Release current resource 50 | data = other.data; // Transfer ownership 51 | other.data = nullptr; // Nullify the source pointer 52 | } 53 | std::cout << "Move Assignment called\n"; 54 | return *this; 55 | } 56 | 57 | void display() const { 58 | if (data) 59 | std::cout << "Value: " << *data << "\n"; 60 | else 61 | std::cout << "Data is null\n"; 62 | } 63 | }; 64 | 65 | int main() { 66 | MyClass obj1(42); // Constructor 67 | MyClass obj2(std::move(obj1)); // Move Constructor 68 | 69 | obj2.display(); 70 | obj1.display(); // Data is null 71 | 72 | MyClass obj3(100); 73 | obj3 = std::move(obj2); // Move Assignment 74 | obj3.display(); 75 | obj2.display(); // Data is null 76 | 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /Object Oriented Programming/oop.md: -------------------------------------------------------------------------------- 1 | # Introduction to Object-Oriented Programming (OOP) in C++ 2 | 3 | ## What is OOP? 4 | Object-Oriented Programming (OOP) is a programming paradigm that is based on the concept of "objects". Objects are instances of classes, which encapsulate data (attributes) and functions (methods) that operate on that data. OOP aims to provide a more intuitive way of organizing and structuring code, making it easier to maintain, reuse, and extend. 5 | 6 | ### Four Core Concepts of OOP: 7 | 1. **Encapsulation**: Bundling of data and methods that manipulate the data into a single unit (class). 8 | 2. **Abstraction**: Hiding the internal implementation and only exposing the functionality. 9 | 3. **Inheritance**: The ability to create new classes from existing classes to reuse and extend functionality. 10 | 4. **Polymorphism**: The ability to use the same interface for different data types or classes. 11 | 12 | --- 13 | 14 | ## Class and Object in C++ 15 | 16 | A **class** is a blueprint for creating objects. An **object** is an instance of a class. 17 | 18 | ### Syntax: 19 | ```cpp 20 | class ClassName { 21 | public: 22 | // Attributes (data members) 23 | int attribute; 24 | 25 | // Methods (member functions) 26 | void display() { 27 | std::cout << "Attribute value: " << attribute << std::endl; 28 | } 29 | }; 30 | 31 | int main() { 32 | ClassName obj; // Creating an object 33 | obj.attribute = 5; // Accessing attribute 34 | obj.display(); // Calling method 35 | return 0; 36 | } 37 | ``` 38 | ### Explanation: 39 | - ClassName: Defines the class. 40 | - obj: An object of type ClassName. 41 | - attribute: A public attribute of the class. 42 | - display(): A method that prints the value of the attribute. 43 | 44 | ## Encapsulation in C++ 45 | Encapsulation is achieved by keeping data members private and providing public methods to access and modify them. 46 | 47 | ### Example: 48 | ```cpp 49 | class Person { 50 | private: 51 | std::string name; 52 | int age; 53 | 54 | public: 55 | void setName(std::string n) { 56 | name = n; 57 | } 58 | 59 | void setAge(int a) { 60 | if (a >= 0) { // Basic validation 61 | age = a; 62 | } 63 | } 64 | 65 | void display() { 66 | std::cout << "Name: " << name << ", Age: " << age << std::endl; 67 | } 68 | }; 69 | 70 | int main() { 71 | Person p; 72 | p.setName("John"); 73 | p.setAge(25); 74 | p.display(); 75 | return 0; 76 | } 77 | ``` 78 | 79 | ### Explanation: 80 | - name and age are private and cannot be accessed directly from outside the class. 81 | - Public methods setName() and setAge() provide controlled access to these private members. 82 | 83 | ## Inheritance in C++ 84 | Inheritance allows one class to inherit properties and behavior from another class. 85 | 86 | ### Example: 87 | ```cpp 88 | class Animal { 89 | public: 90 | void speak() { 91 | std::cout << "Animal sound" << std::endl; 92 | } 93 | }; 94 | 95 | class Dog : public Animal { 96 | public: 97 | void speak() { 98 | std::cout << "Bark!" << std::endl; 99 | } 100 | }; 101 | 102 | int main() { 103 | Animal a; 104 | Dog d; 105 | 106 | a.speak(); // Output: Animal sound 107 | d.speak(); // Output: Bark! 108 | return 0; 109 | } 110 | ``` 111 | ### Explanation: 112 | - Dog class inherits from Animal. 113 | - The Dog class overrides the speak() method of the Animal class. 114 | 115 | ## Polymorphism in C++ 116 | Polymorphism in C++ is achieved through function overriding or overloading, and through pointers and references to base classes. 117 | 118 | ### Example: Runtime Polymorphism (Function Overriding) 119 | ```cpp 120 | class Animal { 121 | public: 122 | virtual void speak() { 123 | std::cout << "Animal sound" << std::endl; 124 | } 125 | }; 126 | 127 | class Dog : public Animal { 128 | public: 129 | void speak() override { 130 | std::cout << "Bark!" << std::endl; 131 | } 132 | }; 133 | 134 | class Cat : public Animal { 135 | public: 136 | void speak() override { 137 | std::cout << "Meow!" << std::endl; 138 | } 139 | }; 140 | 141 | int main() { 142 | Animal* animal1 = new Dog(); 143 | Animal* animal2 = new Cat(); 144 | 145 | animal1->speak(); // Output: Bark! 146 | animal2->speak(); // Output: Meow! 147 | 148 | delete animal1; 149 | delete animal2; 150 | return 0; 151 | } 152 | ``` 153 | ### Explanation: 154 | - The speak() method is marked virtual in the base class Animal to enable polymorphism. 155 | - The Dog and Cat classes override the speak() method to provide specific behavior. 156 | - At runtime, the correct method is invoked based on the actual object type (either Dog or Cat). 157 | 158 | ## Abstraction in C++ 159 | Abstraction focuses on exposing only the essential details while hiding the implementation details. It is commonly achieved using abstract classes and interfaces. 160 | 161 | ### Example: 162 | ```cpp 163 | class Shape { 164 | public: 165 | virtual void draw() = 0; // Pure virtual function 166 | }; 167 | 168 | class Circle : public Shape { 169 | public: 170 | void draw() override { 171 | std::cout << "Drawing Circle" << std::endl; 172 | } 173 | }; 174 | 175 | class Rectangle : public Shape { 176 | public: 177 | void draw() override { 178 | std::cout << "Drawing Rectangle" << std::endl; 179 | } 180 | }; 181 | 182 | int main() { 183 | Shape* shape1 = new Circle(); 184 | Shape* shape2 = new Rectangle(); 185 | 186 | shape1->draw(); // Output: Drawing Circle 187 | shape2->draw(); // Output: Drawing Rectangle 188 | 189 | delete shape1; 190 | delete shape2; 191 | return 0; 192 | } 193 | ``` 194 | ### Explanation: 195 | - Shape is an abstract class with a pure virtual function draw(). 196 | - Circle and Rectangle are concrete classes that implement the draw() function. 197 | -------------------------------------------------------------------------------- /Other Projects/Sudoko.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | #define empty 0 7 | #define N 9 8 | bool isGridSafe(int grid[N][N], int row, int col, int num); 9 | bool isEmptyLocation(int grid[N][N], int &row, int &col); 10 | /* assign values to all the zero (not assigned) values for Sudoku solution 11 | */ 12 | bool SolveSudoku(int grid[N][N]) 13 | { 14 | int row, col; 15 | if (!isEmptyLocation(grid, row, col)) 16 | return true; 17 | for (int num = 1; num <= 9; num++) 18 | { 19 | if (isGridSafe(grid, row, col, num)) 20 | { 21 | grid[row][col] = num; 22 | if (SolveSudoku(grid)) 23 | return true; 24 | grid[row][col] = empty; 25 | } 26 | } 27 | return false; 28 | } 29 | /* Check for entries that don't have a value. */ 30 | bool isEmptyLocation(int grid[N][N], int &row, int &col) 31 | { 32 | for (row = 0; row < N; row++) 33 | for (col = 0; col < N; col++) 34 | if (grid[row][col] == empty) 35 | return true; 36 | return false; 37 | } 38 | /* Returns whether the assigned entry n in the particular row matches 39 | the given number num. */ 40 | bool UsedInRow(int grid[N][N], int prow, int number) 41 | { 42 | for (int col = 0; col < N; col++) 43 | if (grid[prow][col] == number) 44 | return true; 45 | return false; 46 | } 47 | /* Returns true if the number num matches any number in the column */ 48 | bool UsedInCol(int grid[N][N], int pcol, int number) 49 | { 50 | for (int row = 0; row < N; row++) 51 | if (grid[row][pcol] == number) 52 | return true; 53 | else 54 | return false; 55 | } 56 | //Check if the entry used already in the grid box 57 | bool UsedInBox(int grid[N][N], int boxBeginRow, int boxBeginCol, int number) 58 | 59 | { 60 | bool tf = false; 61 | for (int row = 0; row < 3; row++) 62 | for (int col = 0; col < 3; col++) 63 | if (grid[row+boxBeginRow][col+boxBeginCol] == number) 64 | tf = true; 65 | return tf; 66 | } 67 | /* Checks if num can be assigned to a given prow,pcol location. */ 68 | bool isGridSafe(int grid[N][N], int prow, int pcol, int number) 69 | { 70 | return !UsedInRow(grid, prow, number) && !UsedInCol(grid, pcol, number) && 71 | !UsedInBox(grid, prow - prow % 3 , pcol - pcol % 3, number); 72 | } 73 | /* print result */ 74 | void printResult(int finalgrid[N][N]) 75 | { 76 | for (int row = 0; row < N; row++) 77 | { 78 | for (int col = 0; col < N; col++) 79 | cout<< finalgrid[row][col]<<" "; 80 | cout< 2 | 3 | int main() { 4 | int arr[3] = {10, 20, 30}; 5 | int* p = arr; 6 | 7 | std::cout << "Pointer p points to: " << *p << std::endl; 8 | p++; // Move the pointer to the next element in the array 9 | std::cout << "After incrementing, p points to: " << *p << std::endl; 10 | p--; 11 | std::cout << "After decrementing, p points to: " << *p << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/03_pointer_to_pointer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | int* p = &a; 6 | int** pp = &p; // Pointer to pointer 7 | 8 | std::cout << "Value of a: " << a << std::endl; 9 | std::cout << "Value of p: " << *p << std::endl; 10 | std::cout << "Value of pp: " << **pp << std::endl; 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/04_pointers_and_arrays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int arr[3] = {10, 20, 30}; 5 | int* p = arr; 6 | 7 | for(int i = 0; i < 3; i++) { 8 | std::cout << "arr[" << i << "] = " << arr[i] << ", *(p + " << i << ") = " << *(p + i) << std::endl; 9 | } 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/05_pointers_and_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void increment(int* p) { 4 | (*p)++; 5 | } 6 | 7 | int main() { 8 | int a = 10; 9 | increment(&a); 10 | 11 | std::cout << "Value of a after increment: " << a << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/06_void_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | void* p = &a; // Void pointer 6 | 7 | std::cout << "Address stored in p: " << p << std::endl; 8 | 9 | // Dereferencing a void pointer requires casting 10 | std::cout << "Value of a through void pointer: " << *(static_cast(p)) << std::endl; 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/07_null_and_dangling_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int* p = nullptr; // Null pointer 5 | 6 | if (p == nullptr) { 7 | std::cout << "Pointer is null" << std::endl; 8 | } 9 | 10 | // Dangling pointer example 11 | int* q = new int(10); 12 | delete q; 13 | q = nullptr; // Avoid dangling pointer by setting it to null after delete 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/08_const_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | int b = 20; 6 | 7 | const int* p1 = &a; // Pointer to constant (data is constant) 8 | int* const p2 = &a; // Constant pointer (pointer is constant) 9 | const int* const p3 = &a; // Constant pointer to constant 10 | 11 | // *p1 = 30; // Error: Cannot modify data through p1 12 | p1 = &b; // Okay: Can change the pointer 13 | 14 | *p2 = 30; // Okay: Can modify data 15 | // p2 = &b; // Error: Cannot change the pointer 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/09_function_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int add(int a, int b) { 4 | return a + b; 5 | } 6 | 7 | int subtract(int a, int b) { 8 | return a - b; 9 | } 10 | 11 | int main() { 12 | int (*operation)(int, int); // Function pointer 13 | 14 | operation = &add; 15 | std::cout << "Add: " << operation(10, 5) << std::endl; 16 | 17 | operation = &subtract; 18 | std::cout << "Subtract: " << operation(10, 5) << std::endl; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/10_smart_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::unique_ptr p1(new int(10)); // Unique pointer 6 | std::cout << "Value: " << *p1 << std::endl; 7 | 8 | std::shared_ptr p2 = std::make_shared(20); // Shared pointer 9 | std::shared_ptr p3 = p2; // p2 and p3 now share ownership 10 | 11 | std::cout << "Value: " << *p2 << ", Count: " << p2.use_count() << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/Pointers/README.md: -------------------------------------------------------------------------------- 1 | # Pointers in C++ 2 | 3 | ## Overview 4 | 5 | Pointers are a fundamental concept in C++ that allow you to directly work with memory by storing and manipulating the address of variables. Understanding pointers is crucial for effective memory management, dynamic memory allocation, and efficient function handling. 6 | 7 | This folder contains examples and explanations of various pointer concepts in C++. 8 | 9 | ## Table of Contents 10 | 11 | 1. [Basics of Pointers](01_basics_of_pointers.cpp) 12 | 2. [Pointer Arithmetic](02_pointer_arithmetic.cpp) 13 | 3. [Pointers to Pointers](03_pointer_to_pointer.cpp) 14 | 4. [Pointers and Arrays](04_pointers_and_arrays.cpp) 15 | 5. [Pointers and Functions](05_pointers_and_functions.cpp) 16 | 6. [Void Pointers](06_void_pointers.cpp) 17 | 7. [Null and Dangling Pointers](07_null_and_dangling_pointers.cpp) 18 | 8. [Constant Pointers](08_const_pointers.cpp) 19 | 9. [Function Pointers](09_function_pointers.cpp) 20 | 10. [Smart Pointers (Modern C++)](10_smart_pointers.cpp) 21 | 22 | ## 1. Basics of Pointers 23 | 24 | This section introduces pointers, explaining what they are, how to declare them, and how to use them to store the address of variables. [View Code](01_basics_of_pointers.cpp) 25 | 26 | ## 2. Pointer Arithmetic 27 | 28 | Pointers can be incremented or decremented to point to the next or previous memory location. This section demonstrates how pointer arithmetic works. [View Code](02_pointer_arithmetic.cpp) 29 | 30 | ## 3. Pointers to Pointers 31 | 32 | A pointer can also point to another pointer, which is known as a double pointer. This concept is essential in scenarios like dynamic memory allocation. [View Code](03_pointer_to_pointer.cpp) 33 | 34 | ## 4. Pointers and Arrays 35 | 36 | This section explains the relationship between pointers and arrays, showing how pointers can be used to navigate through array elements. [View Code](04_pointers_and_arrays.cpp) 37 | 38 | ## 5. Pointers and Functions 39 | 40 | Pointers can be used to pass arguments to functions by reference, allowing the function to modify the original variables. [View Code](05_pointers_and_functions.cpp) 41 | 42 | ## 6. Void Pointers 43 | 44 | Void pointers are generic pointers that can point to any data type, but they must be cast to the correct type before dereferencing. [View Code](06_void_pointers.cpp) 45 | 46 | ## 7. Null and Dangling Pointers 47 | 48 | Null pointers point to nothing and are often used as a sentinel value. Dangling pointers occur when a pointer still references a memory location that has been freed. [View Code](07_null_and_dangling_pointers.cpp) 49 | 50 | ## 8. Constant Pointers 51 | 52 | This section covers pointers that are constant, meaning the pointer itself or the data it points to cannot be modified. [View Code](08_const_pointers.cpp) 53 | 54 | ## 9. Function Pointers 55 | 56 | Function pointers are pointers that point to the address of a function. This is useful for callback functions and implementing function tables. [View Code](09_function_pointers.cpp) 57 | 58 | ## 10. Smart Pointers (Modern C++) 59 | 60 | Smart pointers, introduced in C++11, automatically manage memory, reducing the risk of memory leaks. This section introduces `std::unique_ptr` and `std::shared_ptr`. [View Code](10_smart_pointers.cpp) 61 | 62 | 63 | 64 | --- 65 | 66 | Each file in this repository provides a simple, self-contained example of the concept being discussed. Feel free to explore the code, run the examples, and modify them to deepen your understanding of pointers in C++. 67 | -------------------------------------------------------------------------------- /Pointers & References/References/01_basics_of_references.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | int& ref = a; // ref is a reference to a 6 | 7 | std::cout << "Value of a: " << a << std::endl; 8 | std::cout << "Value of ref: " << ref << std::endl; 9 | 10 | ref = 20; // Modifies a 11 | std::cout << "Value of a after modifying ref: " << a << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/References/02_references_and_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void increment(int& ref) { 4 | ref++; // Modifies the original variable 5 | } 6 | 7 | int main() { 8 | int a = 10; 9 | increment(a); 10 | 11 | std::cout << "Value of a after increment : " << a << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/References/03_references_and_return_values.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int& getElement(int arr[], int index) { 4 | return arr[index]; // Returns a reference to the element 5 | } 6 | 7 | int main() { 8 | int arr[3] = {10, 20, 30}; 9 | 10 | getElement(arr, 1) = 50; // Modifies the array directly 11 | std::cout << "arr[1] after modification: " << arr[1] << std::endl; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /Pointers & References/References/04_const_references.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void printValue(const int& ref) { 4 | std::cout << "Value: " << ref << std::endl; 5 | // ref++; // Error: Cannot modify a const reference 6 | } 7 | 8 | int main() { 9 | int a = 10; 10 | printValue(a); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Pointers & References/References/05_references_vs_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | int* p = &a; // Pointer 6 | int& ref = a; // Reference 7 | 8 | std::cout << "Pointer p points to: " << *p << std::endl; 9 | std::cout << "Reference ref refers to: " << ref << std::endl; 10 | 11 | p++; // Pointer can be incremented 12 | // ref++; // Error: Reference cannot be incremented 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /Pointers & References/References/06_rvalue_references.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void printValue(int&& ref) { // rvalue reference 4 | std::cout << "Rvalue reference: " << ref << std::endl; 5 | } 6 | 7 | int main() { 8 | int a = 10; 9 | printValue(10); // OK: 10 is an rvalue 10 | // printValue(a); // Error: a is an lvalue 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /Pointers & References/References/README.md: -------------------------------------------------------------------------------- 1 | # References in C++ 2 | 3 | ## Overview 4 | 5 | References in C++ are aliases for existing variables, providing a way to access and modify the original variable directly. Unlike pointers, references must be initialized when declared and cannot be null. They are commonly used for passing arguments to functions efficiently and safely. 6 | 7 | This folder contains examples and explanations of various reference concepts in C++. 8 | 9 | ## Table of Contents 10 | 11 | 1. [Basics of References](01_basics_of_references.cpp) 12 | 2. [References as Function Parameters](02_references_and_functions.cpp) 13 | 3. [References as Return Values](03_references_and_return_values.cpp) 14 | 4. [Constant References](04_const_references.cpp) 15 | 5. [References vs Pointers](05_references_vs_pointers.cpp) 16 | 6. [Rvalue References (C++11 and beyond)](06_rvalue_references.cpp) 17 | 18 | ## 1. Basics of References 19 | 20 | This section introduces references, explaining what they are, how to declare them, and how to use them to create aliases for variables. [View Code](01_basics_of_references.cpp) 21 | 22 | ## 2. References as Function Parameters 23 | 24 | References can be used as function parameters to modify the original argument passed to the function. This allows functions to work directly with the caller's data. [View Code](02_references_and_functions.cpp) 25 | 26 | ## 3. References as Return Values 27 | 28 | Functions can return references, allowing the caller to directly modify the original data returned by the function. This is useful in situations where returning a reference avoids unnecessary copying. [View Code](03_references_and_return_values.cpp) 29 | 30 | ## 4. Constant References 31 | 32 | Constant references prevent modification of the referenced variable. They are commonly used for function parameters when the function should not modify the input. [View Code](04_const_references.cpp) 33 | 34 | ## 5. References vs Pointers 35 | 36 | This section compares references and pointers, highlighting their differences and respective use cases. While both allow access to memory addresses, references provide a safer and simpler syntax in many scenarios. [View Code](05_references_vs_pointers.cpp) 37 | 38 | ## 6. Rvalue References (C++11 and beyond) 39 | 40 | Rvalue references, introduced in C++11, allow you to bind to temporary objects (rvalues). They enable move semantics, which can significantly improve performance by eliminating unnecessary copying. [View Code](06_rvalue_references.cpp) 41 | 42 | --- 43 | 44 | Each file in this repository contains a practical example illustrating a specific aspect of references in C++. Feel free to explore, modify, and experiment with the code to deepen your understanding of references in C++. 45 | -------------------------------------------------------------------------------- /Pointers&References/Pointers/01_basics_of_pointers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int a = 10; 5 | int* p = &a; // Pointer p holds the address of variable a 6 | 7 | std::cout << "Value of a: " << a << std::endl; 8 | std::cout << "Address of a: " << &a << std::endl; 9 | std::cout << "Value of p (Address of a): " << p << std::endl; 10 | std::cout << "Value pointed to by p: " << *p << std::endl; // Dereferencing the pointer 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The **cpp-concepts** repository is designed to help developers understand and implement core C++ concepts. Each concept is explained with detailed comments and code examples to ensure a thorough understanding. 2 | 3 | ## Getting Started 4 | 5 | ### Prerequisites 6 | 7 | To get started with this repository, you need to have the following installed: 8 | 9 | - C++ compiler (e.g., g++, clang++) 10 | - Git 11 | 12 | ### Installation 13 | 14 | 1. Clone the repository: 15 | 16 | ```sh 17 | git clone https://github.com/Helyousfi/cpp-concepts.git 18 | ``` 19 | 20 | 2. Navigate to the project directory: 21 | 22 | ```sh 23 | cd cpp-concepts 24 | ``` 25 | 26 | ## Usage 27 | 28 | ### Examples 29 | 30 | The repository is organized into directories, each focusing on a specific C++ concept. To run an example, navigate to the respective directory and compile the code using your preferred C++ compiler. 31 | 32 | For example, to run an example from the `basics` directory: 33 | 34 | ```sh 35 | cd basics 36 | g++ example.cpp -o example 37 | ./example 38 | ``` 39 | 40 | ## Contributing 41 | 42 | Contributions are welcome! If you have any improvements or new concepts to add, please fork the repository and create a pull request. Follow these steps: 43 | 44 | - Fork the repository 45 | - Create a new branch (git checkout -b feature/your-feature) 46 | - Commit your changes (git commit -m 'Add some feature') 47 | - Push to the branch (git push origin feature/your-feature) 48 | - Open a pull request 49 | - Please ensure your code follows the repository's coding standards and includes appropriate comments and documentation. 50 | 51 | ## Contact 52 | For any questions or suggestions, feel free to open an issue in the repository or contact me directly. 53 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Algorithms/using_algorithms.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | // Example 1: Using std::sort with std::vector 12 | std::cout << "=== Using std::sort with std::vector ===" << std::endl; 13 | std::vector vec = {5, 3, 8, 1, 4}; 14 | 15 | // Sort the vector in ascending order 16 | std::sort(vec.begin(), vec.end()); 17 | 18 | std::cout << "Sorted vector: "; 19 | for (const auto& val : vec) { 20 | std::cout << val << " "; 21 | } 22 | std::cout << std::endl; 23 | 24 | // Example 2: Using std::find with std::vector 25 | std::cout << "\n=== Using std::find with std::vector ===" << std::endl; 26 | auto it = std::find(vec.begin(), vec.end(), 4); 27 | 28 | if (it != vec.end()) { 29 | std::cout << "Found 4 at position: " << std::distance(vec.begin(), it) << std::endl; 30 | } else { 31 | std::cout << "4 not found in the vector" << std::endl; 32 | } 33 | 34 | // Example 3: Using std::accumulate with std::vector 35 | std::cout << "\n=== Using std::accumulate with std::vector ===" << std::endl; 36 | int sum = std::accumulate(vec.begin(), vec.end(), 0); 37 | 38 | std::cout << "Sum of vector elements: " << sum << std::endl; 39 | 40 | // Example 4: Using std::copy with std::list 41 | std::cout << "\n=== Using std::copy with std::list ===" << std::endl; 42 | std::list lst = {1, 2, 3, 4, 5}; 43 | std::vector copyVec(lst.size()); 44 | 45 | std::copy(lst.begin(), lst.end(), copyVec.begin()); 46 | 47 | std::cout << "Copied vector: "; 48 | for (const auto& val : copyVec) { 49 | std::cout << val << " "; 50 | } 51 | std::cout << std::endl; 52 | 53 | // Example 5: Using std::count with std::set 54 | std::cout << "\n=== Using std::count with std::set ===" << std::endl; 55 | std::set st = {1, 2, 3, 4, 5}; 56 | 57 | int count = std::count(st.begin(), st.end(), 3); 58 | 59 | std::cout << "Count of 3 in the set: " << count << std::endl; 60 | 61 | // Example 6: Using std::transform with std::vector 62 | std::cout << "\n=== Using std::transform with std::vector ===" << std::endl; 63 | std::vector transformVec = {1, 2, 3, 4, 5}; 64 | 65 | std::transform(transformVec.begin(), transformVec.end(), transformVec.begin(), 66 | [](int x) { return x * x; }); // Square each element 67 | 68 | std::cout << "Transformed vector (squared values): "; 69 | for (const auto& val : transformVec) { 70 | std::cout << val << " "; 71 | } 72 | std::cout << std::endl; 73 | 74 | // Example 7: Using std::set_intersection with std::set 75 | std::cout << "\n=== Using std::set_intersection with std::set ===" << std::endl; 76 | std::set set1 = {1, 2, 3, 4, 5}; 77 | std::set set2 = {4, 5, 6, 7, 8}; 78 | std::vector intersectionVec; 79 | 80 | std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), 81 | std::back_inserter(intersectionVec)); 82 | 83 | std::cout << "Intersection of sets: "; 84 | for (const auto& val : intersectionVec) { 85 | std::cout << val << " "; 86 | } 87 | std::cout << std::endl; 88 | 89 | // Example 8: Using std::for_each with std::map 90 | std::cout << "\n=== Using std::for_each with std::map ===" << std::endl; 91 | std::map mp = {{1, "one"}, {2, "two"}, {3, "three"}}; 92 | 93 | std::cout << "Map elements: "; 94 | std::for_each(mp.begin(), mp.end(), 95 | [](const std::pair& p) { 96 | std::cout << "[" << p.first << ": " << p.second << "] "; 97 | }); 98 | std::cout << std::endl; 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Associative Containers/01_set.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Creating a set of integers 6 | std::set myset; 7 | 8 | // Inserting elements 9 | myset.insert(10); 10 | myset.insert(20); 11 | myset.insert(30); 12 | myset.insert(20); // Duplicate elements are not added 13 | 14 | // Printing the set 15 | std::cout << "Set elements: "; 16 | for (const int& elem : myset) { 17 | std::cout << elem << ' '; 18 | } 19 | std::cout << std::endl; 20 | 21 | // Checking if an element is in the set 22 | int value = 20; 23 | if (myset.find(value) != myset.end()) { 24 | std::cout << value << " is in the set." << std::endl; 25 | } else { 26 | std::cout << value << " is not in the set." << std::endl; 27 | } 28 | 29 | // Removing elements 30 | myset.erase(20); 31 | std::cout << "After erasing 20: "; 32 | for (const int& elem : myset) { 33 | std::cout << elem << ' '; 34 | } 35 | std::cout << std::endl; 36 | 37 | // Size of the set 38 | std::cout << "Size of the set: " << myset.size() << std::endl; 39 | 40 | // Using iterators 41 | std::cout << "Set elements using iterators: "; 42 | for (std::set::iterator it = myset.begin(); it != myset.end(); ++it) { 43 | std::cout << *it << ' '; 44 | } 45 | std::cout << std::endl; 46 | 47 | // Clearing the set 48 | myset.clear(); 49 | std::cout << "After clearing, size of the set: " << myset.size() << std::endl; 50 | 51 | // Demonstrating a set of strings 52 | std::set strset = {"apple", "banana", "cherry"}; 53 | std::cout << "String set elements: "; 54 | for (const auto& str : strset) { 55 | std::cout << str << ' '; 56 | } 57 | std::cout << std::endl; 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Associative Containers/02_multiset.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | - Implementation Details 3 | 1. Underlying Data Structure: 4 | std::multiset is typically implemented using a 5 | self-balancing binary search tree, such as a Red-Black Tree. 6 | This provides efficient insertions, deletions, and lookups while maintaining order. 7 | 8 | 2. Properties: 9 | - Ordered: Elements are stored in a sorted manner according to the comparator 10 | (by default, std::less). 11 | - Multiple Elements: Allows multiple elements with the same value. 12 | 13 | 3. Performance Characteristics: 14 | - Insertions/Deletions: Average time complexity is O(log n). 15 | - Search: Average time complexity is O(log n). 16 | 17 | */ 18 | #include 19 | #include 20 | 21 | int main() { 22 | // Creating a multiset of integers 23 | std::multiset mymultiset; 24 | 25 | // Inserting elements 26 | mymultiset.insert(10); 27 | mymultiset.insert(20); 28 | mymultiset.insert(30); 29 | mymultiset.insert(20); // Duplicate elements are allowed 30 | mymultiset.insert(10); // Another duplicate 31 | 32 | // Printing the multiset 33 | std::cout << "Multiset elements: "; 34 | for (const int& elem : mymultiset) { 35 | std::cout << elem << ' '; 36 | } 37 | std::cout << std::endl; 38 | 39 | // Counting the number of occurrences of an element 40 | int value = 20; 41 | std::cout << "Number of occurrences of " << value << ": " << mymultiset.count(value) << std::endl; 42 | 43 | // Finding elements 44 | auto it = mymultiset.find(20); 45 | if (it != mymultiset.end()) { 46 | std::cout << "Element 20 found in the multiset." << std::endl; 47 | } else { 48 | std::cout << "Element 20 not found in the multiset." << std::endl; 49 | } 50 | 51 | // Removing elements 52 | mymultiset.erase(20); // Removes all occurrences of 20 53 | std::cout << "After erasing 20: "; 54 | for (const int& elem : mymultiset) { 55 | std::cout << elem << ' '; 56 | } 57 | std::cout << std::endl; 58 | 59 | // Size of the multiset 60 | std::cout << "Size of the multiset: " << mymultiset.size() << std::endl; 61 | 62 | // Using iterators 63 | std::cout << "Multiset elements using iterators: "; 64 | for (std::multiset::iterator it = mymultiset.begin(); it != mymultiset.end(); ++it) { 65 | std::cout << *it << ' '; 66 | } 67 | std::cout << std::endl; 68 | 69 | // Clearing the multiset 70 | mymultiset.clear(); 71 | std::cout << "After clearing, size of the multiset: " << mymultiset.size() << std::endl; 72 | 73 | // Demonstrating a multiset of strings 74 | std::multiset strmultiset = {"apple", "banana", "apple", "cherry"}; 75 | std::cout << "String multiset elements: "; 76 | for (const auto& str : strmultiset) { 77 | std::cout << str << ' '; 78 | } 79 | std::cout << std::endl; 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Associative Containers/03_map.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::map in C++. 2 | // 3 | // Implementation Details: 4 | // - std::map is typically implemented using a self-balancing binary search tree, 5 | // such as a Red-Black Tree. 6 | // - This ensures that all operations such as insertions, deletions, 7 | // and lookups are performed in O(log n) time on average. 8 | // 9 | // Complexity: 10 | // - Insertion: O(log n) 11 | // - Deletion: O(log n) 12 | // - Search: O(log n) 13 | // 14 | // Usage: 15 | // - std::map is used for associative arrays where keys are unique and elements are stored in a sorted order based on the key. 16 | // - It provides fast lookups, insertions, and deletions while maintaining order. 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | int main() { 23 | // Creating a map of string to int 24 | std::map mymap; 25 | 26 | // Inserting elements 27 | mymap["apple"] = 1; 28 | mymap["banana"] = 2; 29 | mymap["cherry"] = 3; 30 | 31 | // Inserting elements using insert function 32 | mymap.insert(std::make_pair("date", 4)); 33 | mymap.insert({"elderberry", 5}); 34 | 35 | // Printing the map 36 | std::cout << "Map elements:\n"; 37 | for (const auto& elem : mymap) { 38 | std::cout << elem.first << ": " << elem.second << '\n'; 39 | } 40 | 41 | // Accessing elements 42 | std::cout << "\nValue for key 'banana': " << mymap["banana"] << '\n'; 43 | 44 | // Modifying elements 45 | mymap["banana"] = 20; 46 | std::cout << "Modified value for key 'banana': " << mymap["banana"] << '\n'; 47 | 48 | // Checking if a key exists 49 | std::string key = "cherry"; 50 | if (mymap.find(key) != mymap.end()) { 51 | std::cout << key << " exists in the map.\n"; 52 | } else { 53 | std::cout << key << " does not exist in the map.\n"; 54 | } 55 | 56 | // Removing elements 57 | mymap.erase("apple"); 58 | std::cout << "\nAfter erasing 'apple':\n"; 59 | for (const auto& elem : mymap) { 60 | std::cout << elem.first << ": " << elem.second << '\n'; 61 | } 62 | 63 | // Size of the map 64 | std::cout << "\nSize of the map: " << mymap.size() << '\n'; 65 | 66 | // Using iterators 67 | std::cout << "\nMap elements using iterators:\n"; 68 | for (std::map::iterator it = mymap.begin(); it != mymap.end(); ++it) { 69 | std::cout << it->first << ": " << it->second << '\n'; 70 | } 71 | 72 | // Clearing the map 73 | mymap.clear(); 74 | std::cout << "\nAfter clearing, size of the map: " << mymap.size() << '\n'; 75 | 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Associative Containers/04_multimap.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::multimap in C++. 2 | // 3 | // Implementation Details: 4 | // - std::multimap is typically implemented using a self-balancing binary search tree, such as a Red-Black Tree. 5 | // - This ensures that all operations such as insertions, deletions, and lookups are performed in O(log n) time on average. 6 | // 7 | // Complexity: 8 | // - Insertion: O(log n) 9 | // - Deletion: O(log n) 10 | // - Search: O(log n) 11 | // 12 | // Usage: 13 | // - std::multimap is used for associative arrays where keys are not unique and elements are stored in a sorted order based on the key. 14 | // - It provides fast lookups, insertions, and deletions while maintaining order, and allows multiple elements with the same key. 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | // Creating a multimap of string to int 22 | std::multimap mymultimap; 23 | 24 | // Inserting elements 25 | mymultimap.insert(std::make_pair("apple", 1)); 26 | mymultimap.insert(std::make_pair("banana", 2)); 27 | mymultimap.insert(std::make_pair("cherry", 3)); 28 | mymultimap.insert(std::make_pair("banana", 4)); // Duplicate key 29 | mymultimap.insert(std::make_pair("apple", 5)); // Another duplicate key 30 | 31 | // Printing the multimap 32 | std::cout << "Multimap elements:\n"; 33 | for (const auto& elem : mymultimap) { 34 | std::cout << elem.first << ": " << elem.second << '\n'; 35 | } 36 | 37 | // Accessing elements with a specific key 38 | std::string key = "banana"; 39 | auto range = mymultimap.equal_range(key); 40 | std::cout << "\nElements with key '" << key << "':\n"; 41 | for (auto it = range.first; it != range.second; ++it) { 42 | std::cout << it->first << ": " << it->second << '\n'; 43 | } 44 | 45 | // Counting occurrences of a specific key 46 | std::cout << "\nNumber of occurrences of '" << key << "': " << mymultimap.count(key) << '\n'; 47 | 48 | // Removing elements with a specific key 49 | mymultimap.erase("apple"); 50 | std::cout << "\nAfter erasing 'apple':\n"; 51 | for (const auto& elem : mymultimap) { 52 | std::cout << elem.first << ": " << elem.second << '\n'; 53 | } 54 | 55 | // Size of the multimap 56 | std::cout << "\nSize of the multimap: " << mymultimap.size() << '\n'; 57 | 58 | // Using iterators 59 | std::cout << "\nMultimap elements using iterators:\n"; 60 | for (std::multimap::iterator it = mymultimap.begin(); it != mymultimap.end(); ++it) { 61 | std::cout << it->first << ": " << it->second << '\n'; 62 | } 63 | 64 | // Clearing the multimap 65 | mymultimap.clear(); 66 | std::cout << "\nAfter clearing, size of the multimap: " << mymultimap.size() << '\n'; 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Container Adapters/01_stack.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::stack in C++. 2 | // 3 | // Implementation Details: 4 | // - std::stack is a container adapter that provides LIFO (Last-In-First-Out) functionality. 5 | // - It is implemented using other underlying containers, typically std::deque or std::vector. 6 | // 7 | // Complexity: 8 | // - Push: O(1) 9 | // - Pop: O(1) 10 | // - Top: O(1) 11 | // - Size: O(1) 12 | // 13 | // Usage: 14 | // - std::stack is used to manage a collection of elements where the last element added is the first to be removed. 15 | 16 | #include 17 | #include 18 | 19 | int main() { 20 | // Creating a stack of integers 21 | std::stack mystack; 22 | 23 | // Pushing elements 24 | mystack.push(1); 25 | mystack.push(2); 26 | mystack.push(3); 27 | 28 | // Printing the top element 29 | std::cout << "Top element: " << mystack.top() << '\n'; 30 | 31 | // Popping elements 32 | mystack.pop(); 33 | std::cout << "Top element after pop: " << mystack.top() << '\n'; 34 | 35 | // Size of the stack 36 | std::cout << "Size of the stack: " << mystack.size() << '\n'; 37 | 38 | // Checking if the stack is empty 39 | std::cout << "Is the stack empty? " << (mystack.empty() ? "Yes" : "No") << '\n'; 40 | 41 | // Clearing the stack 42 | while (!mystack.empty()) { 43 | mystack.pop(); 44 | } 45 | std::cout << "Size of the stack after clearing: " << mystack.size() << '\n'; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Container Adapters/02_queue.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::queue in C++. 2 | // 3 | // Implementation Details: 4 | // - std::queue is a container adapter that provides FIFO (First-In-First-Out) functionality. 5 | // - It is implemented using other underlying containers, typically std::deque or std::list. 6 | // 7 | // Complexity: 8 | // - Push: O(1) 9 | // - Pop: O(1) 10 | // - Front: O(1) 11 | // - Back: O(1) 12 | // - Size: O(1) 13 | // 14 | // Usage: 15 | // - std::queue is used to manage a collection of elements where the first element added is the first to be removed. 16 | 17 | #include 18 | #include 19 | 20 | int main() { 21 | // Creating a queue of integers 22 | std::queue myqueue; 23 | 24 | // Pushing elements 25 | myqueue.push(1); 26 | myqueue.push(2); 27 | myqueue.push(3); 28 | 29 | // Printing the front element 30 | std::cout << "Front element: " << myqueue.front() << '\n'; 31 | 32 | // Printing the back element 33 | std::cout << "Back element: " << myqueue.back() << '\n'; 34 | 35 | // Popping elements 36 | myqueue.pop(); 37 | std::cout << "Front element after pop: " << myqueue.front() << '\n'; 38 | 39 | // Size of the queue 40 | std::cout << "Size of the queue: " << myqueue.size() << '\n'; 41 | 42 | // Checking if the queue is empty 43 | std::cout << "Is the queue empty? " << (myqueue.empty() ? "Yes" : "No") << '\n'; 44 | 45 | // Clearing the queue 46 | while (!myqueue.empty()) { 47 | myqueue.pop(); 48 | } 49 | std::cout << "Size of the queue after clearing: " << myqueue.size() << '\n'; 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Container Adapters/03_priority_queue.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::priority_queue in C++. 2 | // 3 | // Implementation Details: 4 | // - std::priority_queue is a container adapter that provides priority-based access to elements. 5 | // - It is typically implemented using a heap, which is usually a binary heap. 6 | // 7 | // Complexity: 8 | // - Push: O(log n) 9 | // - Pop: O(log n) 10 | // - Top: O(1) 11 | // - Size: O(1) 12 | // 13 | // Usage: 14 | // - std::priority_queue is used to manage a collection of elements where the highest priority element is accessed first. 15 | 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | int main() { 22 | // Creating a priority_queue of integers 23 | std::priority_queue mypriorityqueue; 24 | 25 | // Pushing elements 26 | mypriorityqueue.push(10); 27 | mypriorityqueue.push(5); 28 | mypriorityqueue.push(20); 29 | 30 | // Printing the top element 31 | std::cout << "Top element: " << mypriorityqueue.top() << '\n'; 32 | 33 | // Popping elements 34 | mypriorityqueue.pop(); 35 | std::cout << "Top element after pop: " << mypriorityqueue.top() << '\n'; 36 | 37 | // Size of the priority_queue 38 | std::cout << "Size of the priority_queue: " << mypriorityqueue.size() << '\n'; 39 | 40 | // Checking if the priority_queue is empty 41 | std::cout << "Is the priority_queue empty? " << (mypriorityqueue.empty() ? "Yes" : "No") << '\n'; 42 | 43 | // Clearing the priority_queue 44 | while (!mypriorityqueue.empty()) { 45 | mypriorityqueue.pop(); 46 | } 47 | std::cout << "Size of the priority_queue after clearing: " << mypriorityqueue.size() << '\n'; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/01_vector_construct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // 1. Default constructor: Creates an empty vector. 6 | std::vector vec1; 7 | std::cout << "Size of vec1: " << vec1.size() << std::endl; 8 | 9 | // 2. Fill constructor: Creates a vector with 10 elements, each initialized to 5. 10 | std::vector vec2(10, 5); 11 | std::cout << "Elements of vec2: "; 12 | for (int val : vec2) { 13 | std::cout << val << " "; 14 | } 15 | std::cout << std::endl; 16 | 17 | // 3. Range constructor: Creates a vector from elements in the range [first, last). 18 | int arr[] = {1, 2, 3, 4, 5}; 19 | std::vector vec3(arr, arr + 5); 20 | std::cout << "Elements of vec3: "; 21 | for (int val : vec3) { 22 | std::cout << val << " "; 23 | } 24 | std::cout << std::endl; 25 | 26 | // 4. Copy constructor: Creates a vector as a copy of another vector. 27 | std::vector vec4(vec3); 28 | std::cout << "Elements of vec4 (copy of vec3): "; 29 | for (int val : vec4) { 30 | std::cout << val << " "; 31 | } 32 | std::cout << std::endl; 33 | 34 | // 5. Move constructor: Creates a vector by moving resources from another vector. 35 | std::vector vec5(std::move(vec4)); 36 | std::cout << "Elements of vec5 (moved from vec4): "; 37 | for (int val : vec5) { 38 | std::cout << val << " "; 39 | } 40 | std::cout << std::endl; 41 | std::cout << "Size of vec4 after move: " << vec4.size() << std::endl; 42 | 43 | // 6. Initializer list constructor: Creates a vector from an initializer list. 44 | std::vector vec6 = {10, 20, 30, 40, 50}; 45 | std::cout << "Elements of vec6: "; 46 | for (int val : vec6) { 47 | std::cout << val << " "; 48 | } 49 | std::cout << std::endl; 50 | 51 | // 7. Using emplace_back to construct elements in-place. 52 | std::vector> vec7; 53 | vec7.emplace_back(1, 2); // Constructs a pair(1, 2) in-place. 54 | vec7.emplace_back(3, 4); 55 | std::cout << "Elements of vec7: "; 56 | for (const auto& pair : vec7) { 57 | std::cout << "(" << pair.first << ", " << pair.second << ") "; 58 | } 59 | std::cout << std::endl; 60 | 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/02_vector_element_access.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Initialize a vector with some elements 6 | std::vector numbers = {10, 20, 30, 40, 50}; 7 | 8 | // Access elements using the subscript operator [] 9 | std::cout << "Element at index 0 using []: " << numbers[0] << std::endl; // No bound checking 10 | 11 | // Access elements using the at() method 12 | std::cout << "Element at index 1 using at(): " << numbers.at(1) << std::endl; // You can do numbers.at(1) = 5 13 | 14 | // Access the first element using front() 15 | std::cout << "First element using front(): " << numbers.front() << std::endl; 16 | 17 | // Access the last element using back() 18 | std::cout << "Last element using back(): " << numbers.back() << std::endl; 19 | 20 | // Access the underlying array using data() 21 | int* dataPtr = numbers.data(); 22 | std::cout << "First element using data(): " << *dataPtr << std::endl; 23 | 24 | // Display all elements using a range-based for loop 25 | std::cout << "All elements using range-based for loop: "; 26 | for (const auto& num : numbers) { 27 | std::cout << num << " "; 28 | } 29 | std::cout << std::endl; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/03_vector_modifiers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Modifiers for a vector : 3 | clear, push_back, emplace_back ... 4 | */ 5 | #include 6 | #include 7 | 8 | int main() { 9 | std::vector numbers = {10, 20, 30, 40, 50}; 10 | 11 | // Display the initial state of the vector 12 | std::cout << "Initial vector: "; 13 | for (const auto& num : numbers) { 14 | std::cout << num << " "; 15 | } 16 | std::cout << std::endl; 17 | 18 | // clear(): Removes all elements from the vector 19 | numbers.clear(); 20 | std::cout << "After clear(): Size = " << numbers.size() << std::endl; 21 | 22 | // push_back(): Adds an element to the end 23 | numbers.push_back(10); 24 | numbers.push_back(20); 25 | std::cout << "After push_back(10) and push_back(20): "; 26 | for (const auto& num : numbers) { 27 | std::cout << num << " "; 28 | } 29 | std::cout << std::endl; 30 | 31 | // emplace_back(): Adds an element to the end (more efficient for complex types) 32 | numbers.emplace_back(30); 33 | std::cout << "After emplace_back(30): "; 34 | for (const auto& num : numbers) { 35 | std::cout << num << " "; 36 | } 37 | std::cout << std::endl; 38 | 39 | // insert(): Inserts elements at a specific position 40 | numbers.insert(numbers.begin() + 1, 15); 41 | std::cout << "After insert(15) at position 1: "; 42 | for (const auto& num : numbers) { 43 | std::cout << num << " "; 44 | } 45 | std::cout << std::endl; 46 | 47 | // emplace(): Constructs elements in place at a specific position 48 | numbers.emplace(numbers.begin() + 2, 25); 49 | std::cout << "After emplace(25) at position 2: "; 50 | for (const auto& num : numbers) { 51 | std::cout << num << " "; 52 | } 53 | std::cout << std::endl; 54 | 55 | // erase(): Removes elements at a specific position or range 56 | numbers.erase(numbers.begin() + 1); 57 | std::cout << "After erase element at position 1: "; 58 | for (const auto& num : numbers) { 59 | std::cout << num << " "; 60 | } 61 | std::cout << std::endl; 62 | 63 | // pop_back(): Removes the last element 64 | numbers.pop_back(); 65 | std::cout << "After pop_back(): "; 66 | for (const auto& num : numbers) { 67 | std::cout << num << " "; 68 | } 69 | std::cout << std::endl; 70 | 71 | // resize(): Resizes the container to contain count elements 72 | numbers.resize(5, 100); // If new size is greater, new elements are initialized with 100 73 | std::cout << "After resize(5, 100): "; 74 | for (const auto& num : numbers) { 75 | std::cout << num << " "; 76 | } 77 | std::cout << std::endl; 78 | 79 | // swap(): Swaps the contents with another vector 80 | std::vector otherNumbers = {1, 2, 3}; 81 | numbers.swap(otherNumbers); 82 | std::cout << "After swap with another vector (1, 2, 3): "; 83 | std::cout << "numbers: "; 84 | for (const auto& num : numbers) { 85 | std::cout << num << " "; 86 | } 87 | std::cout << " and otherNumbers: "; 88 | for (const auto& num : otherNumbers) { 89 | std::cout << num << " "; 90 | } 91 | std::cout << std::endl; 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/04_vector_in_place_construction.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Difference between push_back & emplace_back for vectors 3 | */ 4 | #include 5 | #include 6 | #include 7 | 8 | class Person { 9 | public: 10 | std::string name; 11 | int age; 12 | 13 | // Constructor 14 | Person(const std::string& n, int a) : name(n), age(a) { 15 | std::cout << "Constructing Person: " << name << std::endl; 16 | } 17 | 18 | // Copy constructor 19 | Person(const Person& other) : name(other.name), age(other.age) { 20 | std::cout << "Copy Constructing Person: " << name << std::endl; 21 | } 22 | 23 | // Move constructor 24 | Person(Person&& other) noexcept : name(std::move(other.name)), age(other.age) { 25 | std::cout << "Move Constructing Person: " << name << std::endl; 26 | } 27 | }; 28 | 29 | int main() { 30 | std::vector people0; 31 | 32 | // Using push_back 33 | std::cout << "\nUsing push_back:\n"; 34 | people0.push_back(Person("Alice", 30)); 35 | 36 | /* 37 | Output : 38 | Using push_back: 39 | Constructing Person: Alice 40 | Move Constructing Person: Alice 41 | */ 42 | 43 | std::vector people1; 44 | // Using emplace_back 45 | std::cout << "\nUsing emplace_back:\n"; 46 | people1.emplace_back("Bob", 25); 47 | 48 | /* 49 | Output : 50 | Using emplace_back: 51 | Constructing Person: Bob 52 | */ 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/05_array_basic_usage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare an array of 5 integers 6 | std::array arr = {1, 2, 3, 4, 5}; 7 | 8 | // Access elements 9 | std::cout << "First element: " << arr[0] << std::endl; 10 | std::cout << "Second element: " << arr.at(1) << std::endl; // Bounds-checked access 11 | 12 | // Iterate using range-based for loop 13 | std::cout << "Elements: "; 14 | for (const int& elem : arr) { 15 | std::cout << elem << " "; 16 | } 17 | std::cout << std::endl; 18 | 19 | // Size of the array 20 | std::cout << "Array size: " << arr.size() << std::endl; 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/06_array_modify_and_iterators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare and initialize an array 6 | std::array arr = {1, 2, 3, 4, 5}; 7 | 8 | // Modify elements 9 | arr[0] = 10; 10 | arr.at(1) = 20; 11 | 12 | // Iterate using iterators 13 | std::cout << "Elements using iterators: "; 14 | for (auto it = arr.begin(); it != arr.end(); ++it) { 15 | std::cout << *it << " "; 16 | } 17 | std::cout << std::endl; 18 | 19 | // Reverse iteration 20 | std::cout << "Elements in reverse order: "; 21 | for (auto rit = arr.rbegin(); rit != arr.rend(); ++rit) { 22 | std::cout << *rit << " "; 23 | } 24 | std::cout << std::endl; 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/07_array_multidimensional.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare a 2D array 6 | std::array, 2> matrix = 7 | { 8 | {{1, 2, 3}, 9 | {4, 5, 6}} 10 | }; 11 | 12 | // Access elements 13 | std::cout << "Matrix elements:" << std::endl; 14 | for (const auto& row : matrix) { 15 | for (const auto& elem : row) { 16 | std::cout << elem << " "; 17 | } 18 | std::cout << std::endl; 19 | } 20 | 21 | // Modify elements 22 | matrix[0][0] = 10; 23 | matrix[1][2] = 60; 24 | 25 | // Print modified matrix 26 | std::cout << "Modified matrix elements:" << std::endl; 27 | for (const auto& row : matrix) { 28 | for (const auto& elem : row) { 29 | std::cout << elem << " "; 30 | } 31 | std::cout << std::endl; 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/08_array_functions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Function to print elements of an array 5 | void printArray(const std::array& arr) { 6 | for (const int& elem : arr) { 7 | std::cout << elem << " "; 8 | } 9 | std::cout << std::endl; 10 | } 11 | 12 | int main() { 13 | // Declare and initialize an array 14 | std::array arr = {1, 2, 3, 4, 5}; 15 | 16 | // Pass array to a function 17 | std::cout << "Array elements: "; 18 | printArray(arr); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/09_deque_basic_usage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::deque dq = {1, 2, 3, 4, 5}; 6 | 7 | // Access elements 8 | std::cout << "First element: " << dq.front() << std::endl; 9 | std::cout << "Last element: " << dq.back() << std::endl; 10 | 11 | // Iterate using range-based for loop 12 | std::cout << "Elements: "; 13 | for (const int& elem : dq) { 14 | std::cout << elem << " "; 15 | } 16 | std::cout << std::endl; 17 | 18 | // Size of the deque 19 | std::cout << "Deque size: " << dq.size() << std::endl; 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/10_deque_modify_and_iterators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare and initialize a deque 6 | std::deque dq = {1, 2, 3, 4, 5}; 7 | 8 | // Modify elements 9 | dq[0] = 10; 10 | dq.at(1) = 20; 11 | 12 | // Insert and delete elements at both ends 13 | dq.push_front(0); 14 | dq.push_back(6); 15 | dq.pop_front(); 16 | dq.pop_back(); 17 | 18 | // Iterate using iterators 19 | std::cout << "Elements using iterators: "; 20 | for (auto it = dq.begin(); it != dq.end(); ++it) { 21 | std::cout << *it << " "; 22 | } 23 | std::cout << std::endl; 24 | 25 | // Reverse iteration 26 | std::cout << "Elements in reverse order: "; 27 | for (auto rit = dq.rbegin(); rit != dq.rend(); ++rit) { 28 | std::cout << *rit << " "; 29 | } 30 | std::cout << std::endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/11_deque_algorithms.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | // Declaration 7 | std::deque dq = {5, 3, 1, 4, 2}; 8 | 9 | // Sorting 10 | std::sort(dq.begin(), dq.end()); 11 | 12 | // Print sorted elements 13 | std::cout << "Sorted elements: "; 14 | for (const int& elem : dq) { 15 | std::cout << elem << " "; 16 | } 17 | std::cout << std::endl; 18 | 19 | // Find an element 20 | auto it = std::find(dq.begin(), dq.end(), 3); 21 | if (it != dq.end()) { 22 | std::cout << "Element 3 found at position: " << std::distance(dq.begin(), it) << std::endl; 23 | } else { 24 | std::cout << "Element 3 not found" << std::endl; 25 | } 26 | 27 | // Check if all elements satisfy a condition 28 | bool all_positive = std::all_of(dq.begin(), dq.end(), [](int x) { return x > 0; }); 29 | std::cout << "All elements are positive: " << (all_positive ? "true" : "false") << std::endl; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/12_deque_multidimensional.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare a 2D deque 6 | std::deque> matrix = {{1, 2, 3}, {4, 5, 6}}; 7 | 8 | // Access elements 9 | std::cout << "Matrix elements:" << std::endl; 10 | for (const auto& row : matrix) { 11 | for (const auto& elem : row) { 12 | std::cout << elem << " "; 13 | } 14 | std::cout << std::endl; 15 | } 16 | 17 | // Modify elements 18 | matrix[0][0] = 10; 19 | matrix[1][2] = 60; 20 | 21 | // Print modified matrix 22 | std::cout << "Modified matrix elements:" << std::endl; 23 | for (const auto& row : matrix) { 24 | for (const auto& elem : row) { 25 | std::cout << elem << " "; 26 | } 27 | std::cout << std::endl; 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/13_forward_list_basic_usage.cpp: -------------------------------------------------------------------------------- 1 | /// Forward list basics : Signly linked list 2 | 3 | #include 4 | #include 5 | 6 | int main() { 7 | // Declare and initialize a forward list 8 | std::forward_list fwd_list = {1, 2, 3, 4, 5}; 9 | // Access and iterate elements 10 | std::cout << "Elements: "; 11 | for (const int& elem : fwd_list) { 12 | std::cout << elem << " "; 13 | } 14 | std::cout << std::endl; 15 | // Size of the forward list 16 | std::cout << "Forward list size: " << std::distance(fwd_list.begin(), fwd_list.end()) << std::endl; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/14_forward_list_modify_and_iterators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | // Declare and initialize a forward list 6 | std::forward_list fwd_list = {1, 2, 3, 4, 5}; 7 | // Insert elements at the beginning 8 | fwd_list.push_front(0); 9 | // Insert elements after a specific element 10 | auto it = fwd_list.begin(); 11 | ++it; // Move iterator to the second position 12 | fwd_list.insert_after(it, 6); 13 | 14 | // Delete elements 15 | fwd_list.pop_front(); // Removes the first element 16 | it = fwd_list.begin(); 17 | ++it; // Move iterator to the second position 18 | fwd_list.erase_after(it); // Removes the third element 19 | 20 | // Iterate using iterator 21 | std::cout << "Elements using iterator: "; 22 | for (auto it = fwd_list.begin(); it != fwd_list.end(); ++it) { 23 | std::cout << *it << " "; 24 | } 25 | std::cout << std::endl; 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/15_forward_list_algorithms.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | // Declaration 8 | std::forward_list fwd_list = {5, 3, 1, 4, 2}; 9 | 10 | // Sort the forward list (requires a temporary std::vector) 11 | std::vector temp(fwd_list.begin(), fwd_list.end()); 12 | std::sort(temp.begin(), temp.end()); 13 | std::copy(temp.begin(), temp.end(), fwd_list.begin()); 14 | 15 | // Print sorted elements 16 | std::cout << "Sorted elements: "; 17 | for (const int& elem : fwd_list) { 18 | std::cout << elem << " "; 19 | } 20 | std::cout << std::endl; 21 | 22 | // Find an element 23 | auto it = std::find(fwd_list.begin(), fwd_list.end(), 3); 24 | if (it != fwd_list.end()) { 25 | std::cout << "Element 3 found" << std::endl; 26 | } else { 27 | std::cout << "Element 3 not found" << std::endl; 28 | } 29 | 30 | // Check if all elements satisfy a condition 31 | bool all_positive = std::all_of(fwd_list.begin(), fwd_list.end(), [](int x) { return x > 0; }); 32 | std::cout << "All elements are positive: " << (all_positive ? "true" : "false") << std::endl; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/16_list_basic_usage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | std::list myList = {1, 5, 6, 8, 3, 1}; 7 | std::cout << "Printing my list"; 8 | for(int n : myList) 9 | { 10 | std::cout << n << ' '; 11 | } 12 | std::cout << std::endl; 13 | 14 | myList.push_back(6); // Add to the end 15 | myList.push_front(0); // Add to the beginning 16 | 17 | std::cout << "After adding elements: "; 18 | for (int n : myList) { 19 | std::cout << n << ' '; 20 | } 21 | 22 | std::cout << std::endl; 23 | 24 | myList.pop_back(); // Remove from the end 25 | myList.pop_front(); // Remove from the beginning 26 | 27 | for (int n : myList) { 28 | std::cout << n << ' '; 29 | } 30 | std::cout << std::endl; 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/17_list_modify_and_iterators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | std::list mylist = {10, 20, 30, 40, 50}; 6 | 7 | auto it = mylist.begin(); 8 | std::advance(it, 2); // Move iterator to the 3rd position 9 | mylist.insert(it, 25); // Insert 25 before the 3rd element 10 | 11 | std::cout << "After insertion: "; 12 | for (int n : mylist) { 13 | std::cout << n << ' '; 14 | } 15 | std::cout << std::endl; 16 | 17 | // Erasing elements 18 | it = mylist.begin(); 19 | std::advance(it, 1); // Move iterator to the 2nd position 20 | mylist.erase(it); // Erase the 2nd element 21 | 22 | std::cout << "After erasing: "; 23 | for (int n : mylist) { 24 | std::cout << n << ' '; 25 | } 26 | std::cout << std::endl; 27 | 28 | // Modifying elements 29 | for (int& n : mylist) { 30 | n *= 2; // Double each element 31 | } 32 | 33 | std::cout << "After modifying: "; 34 | for (int n : mylist) { 35 | std::cout << n << ' '; 36 | } 37 | std::cout << std::endl; 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Sequence Containers/18_list_algorithms.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::list mylist = {10, 20, 30, 40, 50}; 7 | 8 | // Using iterators to traverse the list 9 | std::cout << "Traversing the list: "; 10 | for (auto it = mylist.begin(); it != mylist.end(); ++it) { 11 | std::cout << *it << ' '; 12 | } 13 | std::cout << std::endl; 14 | 15 | // Using reverse iterators to traverse the list backwards 16 | std::cout << "Traversing the list backwards: "; 17 | for (auto rit = mylist.rbegin(); rit != mylist.rend(); ++rit) { 18 | std::cout << *rit << ' '; 19 | } 20 | std::cout << std::endl; 21 | 22 | // Using standard algorithms 23 | // Find an element 24 | auto it = std::find(mylist.begin(), mylist.end(), 30); 25 | if (it != mylist.end()) { 26 | std::cout << "Element 30 found in the list." << std::endl; 27 | } else { 28 | std::cout << "Element 30 not found in the list." << std::endl; 29 | } 30 | 31 | // Sort the list 32 | mylist.sort(); 33 | std::cout << "List after sorting: "; 34 | for (int n : mylist) { 35 | std::cout << n << ' '; 36 | } 37 | std::cout << std::endl; 38 | 39 | // Remove duplicates 40 | mylist.unique(); 41 | std::cout << "List after removing duplicates: "; 42 | for (int n : mylist) { 43 | std::cout << n << ' '; 44 | } 45 | std::cout << std::endl; 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Unordered Associative Containers/01_unordered_set.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::unordered_set in C++. 2 | // 3 | // Implementation Details: 4 | // - std::unordered_set is implemented using a hash table. 5 | // - It provides average-case O(1) time complexity for insertions, deletions, and lookups. 6 | // - The elements are not stored in any specific order. 7 | // 8 | // Complexity: 9 | // - Insertion: Average O(1), worst-case O(n) if many collisions occur 10 | // - Deletion: Average O(1), worst-case O(n) 11 | // - Search: Average O(1), worst-case O(n) 12 | // 13 | // Usage: 14 | // - std::unordered_set is used for storing unique elements with fast average-time complexity operations. 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | // Creating an unordered_set of strings 22 | std::unordered_set myunorderedset; 23 | 24 | // Inserting elements 25 | myunorderedset.insert("apple"); 26 | myunorderedset.insert("banana"); 27 | myunorderedset.insert("cherry"); 28 | 29 | // Printing the unordered_set 30 | std::cout << "Unordered set elements:\n"; 31 | for (const auto& elem : myunorderedset) { 32 | std::cout << elem << '\n'; 33 | } 34 | 35 | // Checking if an element exists 36 | std::string key = "banana"; 37 | if (myunorderedset.find(key) != myunorderedset.end()) { 38 | std::cout << key << " exists in the unordered set.\n"; 39 | } else { 40 | std::cout << key << " does not exist in the unordered set.\n"; 41 | } 42 | 43 | // Removing elements 44 | myunorderedset.erase("apple"); 45 | std::cout << "\nAfter erasing 'apple':\n"; 46 | for (const auto& elem : myunorderedset) { 47 | std::cout << elem << '\n'; 48 | } 49 | 50 | // Size of the unordered_set 51 | std::cout << "\nSize of the unordered set: " << myunorderedset.size() << '\n'; 52 | 53 | // Using iterators 54 | std::cout << "\nUnordered set elements using iterators:\n"; 55 | for (std::unordered_set::iterator it = myunorderedset.begin(); it != myunorderedset.end(); ++it) { 56 | std::cout << *it << '\n'; 57 | } 58 | 59 | // Clearing the unordered_set 60 | myunorderedset.clear(); 61 | std::cout << "\nAfter clearing, size of the unordered set: " << myunorderedset.size() << '\n'; 62 | 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Unordered Associative Containers/02_unordered_multiset.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::unordered_multiset in C++. 2 | // 3 | // Implementation Details: 4 | // - std::unordered_multiset is implemented using a hash table. 5 | // - It provides average-case O(1) time complexity for insertions, deletions, and lookups. 6 | // - The elements are not stored in any specific order and multiple elements with the same value are allowed. 7 | // 8 | // Complexity: 9 | // - Insertion: Average O(1), worst-case O(n) if many collisions occur 10 | // - Deletion: Average O(1), worst-case O(n) 11 | // - Search: Average O(1), worst-case O(n) 12 | // 13 | // Usage: 14 | // - std::unordered_multiset is used for storing multiple elements with the same value and provides fast average-time complexity operations. 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | int main() { 21 | // Creating an unordered_multiset of strings 22 | std::unordered_multiset myunorderedmultiset; 23 | 24 | // Inserting elements 25 | myunorderedmultiset.insert("apple"); 26 | myunorderedmultiset.insert("banana"); 27 | myunorderedmultiset.insert("cherry"); 28 | myunorderedmultiset.insert("banana"); // Duplicate element 29 | myunorderedmultiset.insert("apple"); // Another duplicate element 30 | 31 | // Printing the unordered_multiset 32 | std::cout << "Unordered multiset elements:\n"; 33 | for (const auto& elem : myunorderedmultiset) { 34 | std::cout << elem << '\n'; 35 | } 36 | 37 | // Accessing elements with a specific value 38 | std::string key = "banana"; 39 | auto range = myunorderedmultiset.equal_range(key); 40 | std::cout << "\nElements with value '" << key << "':\n"; 41 | for (auto it = range.first; it != range.second; ++it) { 42 | std::cout << *it << '\n'; 43 | } 44 | 45 | // Counting occurrences of a specific value 46 | std::cout << "\nNumber of occurrences of '" << key << "': " << myunorderedmultiset.count(key) << '\n'; 47 | 48 | // Removing elements with a specific value 49 | myunorderedmultiset.erase("apple"); 50 | std::cout << "\nAfter erasing 'apple':\n"; 51 | for (const auto& elem : myunorderedmultiset) { 52 | std::cout << elem << '\n'; 53 | } 54 | 55 | // Size of the unordered_multiset 56 | std::cout << "\nSize of the unordered multiset: " << myunorderedmultiset.size() << '\n'; 57 | 58 | // Using iterators 59 | std::cout << "\nUnordered multiset elements using iterators:\n"; 60 | for (std::unordered_multiset::iterator it = myunorderedmultiset.begin(); it != myunorderedmultiset.end(); ++it) { 61 | std::cout << *it << '\n'; 62 | } 63 | 64 | // Clearing the unordered_multiset 65 | myunorderedmultiset.clear(); 66 | std::cout << "\nAfter clearing, size of the unordered multiset: " << myunorderedmultiset.size() << '\n'; 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Unordered Associative Containers/03_unordered_map.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::unordered_map in C++. 2 | // 3 | // Implementation Details: 4 | // - std::unordered_map is implemented using a hash table. 5 | // - It provides average-case O(1) time complexity for insertions, deletions, and lookups. 6 | // - The keys are not stored in any specific order. 7 | // 8 | // Complexity: 9 | // - Insertion: Average O(1), worst-case O(n) if many collisions occur 10 | // - Deletion: Average O(1), worst-case O(n) 11 | // - Search: Average O(1), worst-case O(n) 12 | // 13 | // Usage: 14 | // - std::unordered_map is used for associative arrays where keys are unique and elements are accessed via hash-based indexing. 15 | // - It provides fast average-time complexity operations and does not maintain any order among the keys. 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | int main() { 22 | // Creating an unordered_map of string to int 23 | std::unordered_map myunorderedmap; 24 | 25 | // Inserting elements 26 | myunorderedmap["apple"] = 1; 27 | myunorderedmap["banana"] = 2; 28 | myunorderedmap["cherry"] = 3; 29 | 30 | // Inserting elements using insert function 31 | myunorderedmap.insert(std::make_pair("date", 4)); 32 | myunorderedmap.insert({"elderberry", 5}); 33 | 34 | // Printing the unordered_map 35 | std::cout << "Unordered map elements:\n"; 36 | for (const auto& elem : myunorderedmap) { 37 | std::cout << elem.first << ": " << elem.second << '\n'; 38 | } 39 | 40 | // Accessing elements 41 | std::cout << "\nValue for key 'banana': " << myunorderedmap["banana"] << '\n'; 42 | 43 | // Modifying elements 44 | myunorderedmap["banana"] = 20; 45 | std::cout << "Modified value for key 'banana': " << myunorderedmap["banana"] << '\n'; 46 | 47 | // Checking if a key exists 48 | std::string key = "cherry"; 49 | if (myunorderedmap.find(key) != myunorderedmap.end()) { 50 | std::cout << key << " exists in the unordered map.\n"; 51 | } else { 52 | std::cout << key << " does not exist in the unordered map.\n"; 53 | } 54 | 55 | // Removing elements 56 | myunorderedmap.erase("apple"); 57 | std::cout << "\nAfter erasing 'apple':\n"; 58 | for (const auto& elem : myunorderedmap) { 59 | std::cout << elem.first << ": " << elem.second << '\n'; 60 | } 61 | 62 | // Size of the unordered_map 63 | std::cout << "\nSize of the unordered map: " << myunorderedmap.size() << '\n'; 64 | 65 | // Using iterators 66 | std::cout << "\nUnordered map elements using iterators:\n"; 67 | for (std::unordered_map::iterator it = myunorderedmap.begin(); it != myunorderedmap.end(); ++it) { 68 | std::cout << it->first << ": " << it->second << '\n'; 69 | } 70 | 71 | // Clearing the unordered_map 72 | myunorderedmap.clear(); 73 | std::cout << "\nAfter clearing, size of the unordered map: " << myunorderedmap.size() << '\n'; 74 | 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/Unordered Associative Containers/04_unordered_multimap.cpp: -------------------------------------------------------------------------------- 1 | // This file demonstrates the usage of std::unordered_multimap in C++. 2 | // 3 | // Implementation Details: 4 | // - std::unordered_multimap is implemented using a hash table. 5 | // - It provides average-case O(1) time complexity for insertions, deletions, and lookups. 6 | // - The keys are not stored in any specific order and multiple elements with the same key are allowed. 7 | // 8 | // Complexity: 9 | // - Insertion: Average O(1), worst-case O(n) if many collisions occur 10 | // - Deletion: Average O(1), worst-case O(n) 11 | // - Search: Average O(1), worst-case O(n) 12 | // 13 | // Usage: 14 | // - std::unordered_multimap is used for associative arrays where keys are not unique and elements are accessed via hash-based indexing. 15 | // - It provides fast average-time complexity operations and allows multiple elements with the same key. 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | int main() { 22 | // Creating an unordered_multimap of string to int 23 | std::unordered_multimap myunorderedmultimap; 24 | 25 | // Inserting elements 26 | myunorderedmultimap.insert(std::make_pair("apple", 1)); 27 | myunorderedmultimap.insert(std::make_pair("banana", 2)); 28 | myunorderedmultimap.insert(std::make_pair("cherry", 3)); 29 | myunorderedmultimap.insert(std::make_pair("banana", 4)); // Duplicate key 30 | myunorderedmultimap.insert(std::make_pair("apple", 5)); // Another duplicate key 31 | 32 | // Printing the unordered_multimap 33 | std::cout << "Unordered multimap elements:\n"; 34 | for (const auto& elem : myunorderedmultimap) { 35 | std::cout << elem.first << ": " << elem.second << '\n'; 36 | } 37 | 38 | // Accessing elements with a specific key 39 | std::string key = "banana"; 40 | auto range = myunorderedmultimap.equal_range(key); 41 | std::cout << "\nElements with key '" << key << "':\n"; 42 | for (auto it = range.first; it != range.second; ++it) { 43 | std::cout << it->first << ": " << it->second << '\n'; 44 | } 45 | 46 | // Counting occurrences of a specific key 47 | std::cout << "\nNumber of occurrences of '" << key << "': " << myunorderedmultimap.count(key) << '\n'; 48 | 49 | // Removing elements with a specific key 50 | myunorderedmultimap.erase("apple"); 51 | std::cout << "\nAfter erasing 'apple':\n"; 52 | for (const auto& elem : myunorderedmultimap) { 53 | std::cout << elem.first << ": " << elem.second << '\n'; 54 | } 55 | 56 | // Size of the unordered_multimap 57 | std::cout << "\nSize of the unordered multimap: " << myunorderedmultimap.size() << '\n'; 58 | 59 | // Using iterators 60 | std::cout << "\nUnordered multimap elements using iterators:\n"; 61 | for (std::unordered_multimap::iterator it = myunorderedmultimap.begin(); it != myunorderedmultimap.end(); ++it) { 62 | std::cout << it->first << ": " << it->second << '\n'; 63 | } 64 | 65 | // Clearing the unordered_multimap 66 | myunorderedmultimap.clear(); 67 | std::cout << "\nAfter clearing, size of the unordered multimap: " << myunorderedmultimap.size() << '\n'; 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/readme.md: -------------------------------------------------------------------------------- 1 | # C++ STL Containers 2 | 3 | The C++ Standard Template Library (STL) provides a rich set of template classes for managing collections of data. This README explains the different types of STL containers, their typical use cases, and some details about their implementation. 4 | 5 | ## Table of Contents 6 | 7 | - [C++ STL Containers](#c-stl-containers) 8 | - [Table of Contents](#table-of-contents) 9 | - [Introduction](#introduction) 10 | - [Sequence Containers](#sequence-containers) 11 | - [Vector](#vector) 12 | - [Deque](#deque) 13 | - [List](#list) 14 | - [Forward List](#forward-list) 15 | - [Array](#array) 16 | - [Associative Containers](#associative-containers) 17 | - [Set](#set) 18 | - [Multiset](#multiset) 19 | - [Map](#map) 20 | - [Multimap](#multimap) 21 | - [Unordered Associative Containers](#unordered-associative-containers) 22 | - [Unordered Set](#unordered-set) 23 | - [Unordered Multiset](#unordered-multiset) 24 | - [Unordered Map](#unordered-map) 25 | - [Unordered Multimap](#unordered-multimap) 26 | - [Container Adapters](#container-adapters) 27 | - [Stack](#stack) 28 | - [Queue](#queue) 29 | - [Priority Queue](#priority-queue) 30 | - [Conclusion](#conclusion) 31 | 32 | ## Introduction 33 | 34 | The STL containers are designed to handle various data storage needs. They are categorized based on their functionality and underlying implementation. 35 | 36 | ## Sequence Containers 37 | 38 | Sequence containers maintain the ordering of elements and allow access to elements using iterators or indexes. 39 | 40 | ### Vector 41 | 42 | - **Description**: A dynamic array that can grow and shrink in size. 43 | - **Implementation**: Typically implemented using a contiguous block of memory. 44 | - **Key Operations**: 45 | - **Access**: Random access via the subscript operator (`[]`) and `at()`. 46 | - **Insertion/Deletion**: Efficient at the end (`push_back`, `pop_back`), less efficient in the middle. 47 | - **Use Case**: When you need random access to elements and fast insertion/deletion at the end. 48 | 49 | ### Deque 50 | 51 | - **Description**: A double-ended queue that allows fast insertions and deletions at both ends. 52 | - **Implementation**: Often implemented as a sequence of contiguous memory blocks. 53 | - **Key Operations**: 54 | - **Access**: Random access via the subscript operator (`[]`) and `at()`. 55 | - **Insertion/Deletion**: Efficient at both ends (`push_front`, `push_back`, `pop_front`, `pop_back`). 56 | - **Use Case**: When you need to add or remove elements from both ends and require random access. 57 | 58 | ### List 59 | 60 | - **Description**: A doubly-linked list allowing efficient insertions and deletions anywhere in the list. 61 | - **Implementation**: Doubly-linked list. 62 | - **Key Operations**: 63 | - **Access**: Sequential access only (no random access). 64 | - **Insertion/Deletion**: Efficient anywhere in the list. 65 | - **Use Case**: When you need efficient insertions and deletions at arbitrary positions. 66 | 67 | ### Forward List 68 | 69 | - **Description**: A singly-linked list with efficient insertions and deletions at the front. 70 | - **Implementation**: Singly-linked list. 71 | - **Key Operations**: 72 | - **Access**: Sequential access only (no random access). 73 | - **Insertion/Deletion**: Efficient at the front. 74 | - **Use Case**: When you need a lightweight list with efficient operations at the front. 75 | 76 | ### Array 77 | 78 | - **Description**: A fixed-size array with a constant size determined at compile time. 79 | - **Implementation**: Contiguous block of memory. 80 | - **Key Operations**: 81 | - **Access**: Random access via the subscript operator (`[]`). 82 | - **Insertion/Deletion**: Not supported; fixed size. 83 | - **Use Case**: When you need a fixed-size collection with fast access and no dynamic resizing. 84 | 85 | ## Associative Containers 86 | 87 | Associative containers store elements in a specific order based on keys or values. 88 | 89 | ### Set 90 | 91 | - **Description**: A collection of unique elements stored in a sorted order. 92 | - **Implementation**: Typically implemented as a balanced binary search tree (e.g., Red-Black Tree). 93 | - **Key Operations**: 94 | - **Insertion/Deletion**: Logarithmic time complexity. 95 | - **Access**: Efficient searching, insertion, and deletion. 96 | - **Use Case**: When you need a collection of unique elements with automatic sorting. 97 | 98 | ### Multiset 99 | 100 | - **Description**: Similar to `set`, but allows duplicate elements. 101 | - **Implementation**: Same as `set` (usually a balanced binary search tree). 102 | - **Key Operations**: 103 | - **Insertion/Deletion**: Logarithmic time complexity. 104 | - **Access**: Efficient searching and insertion of duplicate elements. 105 | - **Use Case**: When you need a collection of elements where duplicates are allowed. 106 | 107 | ### Map 108 | 109 | - **Description**: A collection of key-value pairs with unique keys, stored in a sorted order by keys. 110 | - **Implementation**: Typically implemented as a balanced binary search tree (e.g., Red-Black Tree). 111 | - **Key Operations**: 112 | - **Insertion/Deletion**: Logarithmic time complexity. 113 | - **Access**: Efficient access to values by key. 114 | - **Use Case**: When you need a dictionary-like data structure with unique keys. 115 | 116 | ### Multimap 117 | 118 | - **Description**: Similar to `map`, but allows multiple values for a single key. 119 | - **Implementation**: Same as `map` (usually a balanced binary search tree). 120 | - **Key Operations**: 121 | - **Insertion/Deletion**: Logarithmic time complexity. 122 | - **Access**: Efficient access to values with duplicate keys. 123 | - **Use Case**: When you need a dictionary-like structure where multiple values can be associated with a single key. 124 | 125 | ## Unordered Associative Containers 126 | 127 | Unordered associative containers use hashing to provide average-case constant time complexity for operations. 128 | 129 | ### Unordered Set 130 | 131 | - **Description**: A collection of unique elements using a hash table. 132 | - **Implementation**: Hash table. 133 | - **Key Operations**: 134 | - **Insertion/Deletion/Access**: Average-case constant time complexity. 135 | - **Order**: Elements are not stored in any specific order. 136 | - **Use Case**: When you need fast access and do not require sorted elements. 137 | 138 | ### Unordered Multiset 139 | 140 | - **Description**: Similar to `unordered_set`, but allows duplicate elements. 141 | - **Implementation**: Hash table. 142 | - **Key Operations**: 143 | - **Insertion/Deletion/Access**: Average-case constant time complexity. 144 | - **Order**: Elements are not stored in any specific order. 145 | - **Use Case**: When you need a fast collection of elements where duplicates are allowed. 146 | 147 | ### Unordered Map 148 | 149 | - **Description**: A collection of key-value pairs with unique keys, using a hash table. 150 | - **Implementation**: Hash table. 151 | - **Key Operations**: 152 | - **Insertion/Deletion/Access**: Average-case constant time complexity. 153 | - **Order**: Keys are not stored in any specific order. 154 | - **Use Case**: When you need fast access to values by key and do not require sorted keys. 155 | 156 | ### Unordered Multimap 157 | 158 | - **Description**: Similar to `unordered_map`, but allows multiple values for a single key. 159 | - **Implementation**: Hash table. 160 | - **Key Operations**: 161 | - **Insertion/Deletion/Access**: Average-case constant time complexity. 162 | - **Order**: Keys are not stored in any specific order. 163 | - **Use Case**: When you need fast access to values with duplicate keys and do not require sorted keys. 164 | 165 | ## Container Adapters 166 | 167 | Container adapters provide specific functionalities built on top of other container types. 168 | 169 | ### Stack 170 | 171 | - **Description**: A container adapter that provides LIFO (Last-In-First-Out) functionality. 172 | - **Implementation**: Typically built using `std::deque` or `std::vector`. 173 | - **Key Operations**: 174 | - **Push**: Add elements to the top. 175 | - **Pop**: Remove elements from the top. 176 | - **Top**: Access the top element. 177 | - **Use Case**: When you need a stack with LIFO behavior. 178 | 179 | ### Queue 180 | 181 | - **Description**: A container adapter that provides FIFO (First-In-First-Out) functionality. 182 | - **Implementation**: Typically built using `std::deque` or `std::list`. 183 | - **Key Operations**: 184 | - **Push**: Add elements to the back. 185 | - **Pop**: Remove elements from the front. 186 | - **Front**: Access the front element. 187 | - **Back**: Access the back element. 188 | - **Use Case**: When you need a queue with FIFO behavior. 189 | 190 | ### Priority Queue 191 | 192 | - **Description**: A container adapter that provides access to elements based on priority (highest priority first). 193 | - **Implementation**: Typically built using a heap data structure. 194 | - **Key Operations**: 195 | - **Push**: Add elements with a priority. 196 | - **Pop**: Remove the element with the highest priority. 197 | - **Top**: Access the element with the highest priority. 198 | - **Use Case**: When you need to manage elements with varying priorities. 199 | 200 | ## Conclusion 201 | 202 | STL containers offer a wide range of functionalities to manage collections of data efficiently. Choosing the right container depends on your specific needs, such as the type of access required, whether you need ordering or uniqueness, 203 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Containers/sequence_containers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helyousfi/cpp-concepts/f0f0730fb5fe20412c21ce6c6ae04d8d94d33e5e/STL (Standard Template Library)/Containers/sequence_containers.png -------------------------------------------------------------------------------- /STL (Standard Template Library)/Iterators/readme.md: -------------------------------------------------------------------------------- 1 | # C++ Iterators Overview 2 | 3 | Iterators are a fundamental concept in C++ STL that allow you to traverse and access elements of containers. They provide a consistent way to access elements regardless of the underlying container type. Understanding iterators is crucial for working with STL containers and algorithms effectively. 4 | 5 | ## Table of Contents 6 | 7 | - [C++ Iterators Overview](#c-iterators-overview) 8 | - [Table of Contents](#table-of-contents) 9 | - [What is an Iterator?](#what-is-an-iterator) 10 | - [Types of Iterators](#types-of-iterators) 11 | - [Input Iterators](#input-iterators) 12 | - [Output Iterators](#output-iterators) 13 | - [Forward Iterators](#forward-iterators) 14 | - [Bidirectional Iterators](#bidirectional-iterators) 15 | - [Random Access Iterators](#random-access-iterators) 16 | - [Using Iterators](#using-iterators) 17 | 18 | ## What is an Iterator? 19 | 20 | An iterator is an object that enables you to traverse through the elements of a container, such as `std::vector`, `std::list`, or `std::map`. Iterators provide a uniform way to access elements and are used extensively in C++ STL algorithms. 21 | 22 | Key characteristics of iterators: 23 | - **Dereferencing**: Access the element pointed to by the iterator. 24 | - **Incrementing/Decrementing**: Move the iterator to the next/previous element. 25 | - **Comparison**: Check if two iterators are equal or not. 26 | 27 | ## Types of Iterators 28 | 29 | Different containers provide different types of iterators based on their functionality and the operations they support. 30 | 31 | ### Input Iterators 32 | 33 | - **Description**: Support reading elements from a container in a single-pass manner. 34 | - **Operations**: 35 | - **Dereferencing**: Access the element (`*iterator`). 36 | - **Incrementing**: Move to the next element (`++iterator`). 37 | - **Equality/Inequality**: Compare iterators (`iterator1 == iterator2`). 38 | 39 | ### Output Iterators 40 | 41 | - **Description**: Support writing elements to a container in a single-pass manner. 42 | - **Operations**: 43 | - **Dereferencing**: Write to the element (`*iterator = value`). 44 | - **Incrementing**: Move to the next position (`++iterator`). 45 | 46 | ### Forward Iterators 47 | 48 | - **Description**: Support reading and writing elements multiple times and can move forward. 49 | - **Operations**: 50 | - **Dereferencing**: Access and modify the element. 51 | - **Incrementing**: Move to the next element. 52 | - **Equality/Inequality**: Compare iterators. 53 | - **Multi-pass**: Can be used multiple times. 54 | 55 | ### Bidirectional Iterators 56 | 57 | - **Description**: Extend forward iterators with the ability to move both forward and backward. 58 | - **Operations**: 59 | - **Dereferencing**: Access and modify the element. 60 | - **Incrementing/Decrementing**: Move to the next or previous element (`++iterator`, `--iterator`). 61 | 62 | ### Random Access Iterators 63 | 64 | - **Description**: Extend bidirectional iterators with direct access to any element in constant time. 65 | - **Operations**: 66 | - **Dereferencing**: Access and modify the element. 67 | - **Incrementing/Decrementing**: Move to the next or previous element. 68 | - **Random Access**: Access elements by offset (`iterator + n`, `iterator[n]`). 69 | - **Comparison**: Compare iterators and calculate distance (`iterator1 < iterator2`). 70 | 71 | ## Using Iterators 72 | 73 | Iterators are used with STL algorithms and container member functions. Here’s an example of using iterators with `std::vector`: 74 | 75 | ```cpp 76 | #include 77 | #include 78 | 79 | int main() { 80 | std::vector vec = {1, 2, 3, 4, 5}; 81 | 82 | // Using iterators to traverse the vector 83 | for (std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { 84 | std::cout << *it << " "; // Dereferencing iterator to get value 85 | } 86 | std::cout << std::endl; 87 | 88 | // Using reverse iterators 89 | for (std::vector::reverse_iterator rit = vec.rbegin(); rit != vec.rend(); ++rit) { 90 | std::cout << *rit << " "; // Dereferencing reverse iterator 91 | } 92 | std::cout << std::endl; 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /STL (Standard Template Library)/Iterators/using_iterators.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | // Example 1: Using Iterators with std::vector 9 | std::cout << "=== Using Iterators with std::vector ===" << std::endl; 10 | std::vector vec = {10, 20, 30, 40, 50}; 11 | 12 | // Using forward iterators to traverse and print the vector 13 | std::cout << "Vector elements: "; 14 | for (std::vector::iterator it = vec.begin(); it != vec.end(); ++it) { 15 | std::cout << *it << " "; 16 | } 17 | std::cout << std::endl; 18 | 19 | // Using reverse iterators to traverse and print the vector in reverse 20 | std::cout << "Vector elements in reverse: "; 21 | for (std::vector::reverse_iterator rit = vec.rbegin(); rit != vec.rend(); ++rit) { 22 | std::cout << *rit << " "; 23 | } 24 | std::cout << std::endl; 25 | 26 | // Example 2: Using Iterators with std::list 27 | std::cout << "\n=== Using Iterators with std::list ===" << std::endl; 28 | std::list lst = {1, 2, 3, 4, 5}; 29 | 30 | // Using bidirectional iterators to traverse and print the list 31 | std::cout << "List elements: "; 32 | for (std::list::iterator it = lst.begin(); it != lst.end(); ++it) { 33 | std::cout << *it << " "; 34 | } 35 | std::cout << std::endl; 36 | 37 | // Example 3: Using Iterators with std::set 38 | std::cout << "\n=== Using Iterators with std::set ===" << std::endl; 39 | std::set st = {5, 3, 8, 1, 4}; 40 | 41 | // Using bidirectional iterators to traverse and print the set 42 | std::cout << "Set elements: "; 43 | for (std::set::iterator it = st.begin(); it != st.end(); ++it) { 44 | std::cout << *it << " "; 45 | } 46 | std::cout << std::endl; 47 | 48 | // Example 4: Using Iterators with std::map 49 | std::cout << "\n=== Using Iterators with std::map ===" << std::endl; 50 | std::map mp = {{1, "one"}, {2, "two"}, {3, "three"}}; 51 | 52 | // Using bidirectional iterators to traverse and print the map 53 | std::cout << "Map elements: "; 54 | for (std::map::iterator it = mp.begin(); it != mp.end(); ++it) { 55 | std::cout << "[" << it->first << ": " << it->second << "] "; 56 | } 57 | std::cout << std::endl; 58 | 59 | // Using constant iterators for read-only access to map elements 60 | std::cout << "Map elements using const iterator: "; 61 | for (std::map::const_iterator it = mp.cbegin(); it != mp.cend(); ++it) { 62 | std::cout << "[" << it->first << ": " << it->second << "] "; 63 | } 64 | std::cout << std::endl; 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /Smart Pointers/shared_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class MyClass { 5 | public: 6 | MyClass() { std::cout << "MyClass constructed\n"; } 7 | ~MyClass() { std::cout << "MyClass destructed\n"; } 8 | void show() { std::cout << "MyClass::show() called\n"; } 9 | }; 10 | 11 | int main() { 12 | std::shared_ptr ptr1 = std::make_shared(); 13 | ptr1->show(); 14 | 15 | { 16 | std::shared_ptr ptr2 = ptr1; // ptr2 shares ownership with ptr1 17 | ptr2->show(); 18 | std::cout << "Use count: " << ptr1.use_count() << "\n"; // Output: 2 19 | } // ptr2 goes out of scope, but object is not destroyed because ptr1 still exists 20 | 21 | std::cout << "Use count after ptr2 is out of scope: " << ptr1.use_count() << "\n"; // Output: 1 22 | // Object is destroyed when ptr1 goes out of scope 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /Smart Pointers/unique_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Car 5 | { 6 | public: 7 | Car(); 8 | ~Car(); 9 | void Show(); 10 | }; 11 | 12 | Car::Car(){ 13 | std::cout << "Car constructed succussfully!" << std::endl; 14 | } 15 | 16 | Car::~Car(){ 17 | std::cout << "Car destructed succussfully!" << std::endl; 18 | } 19 | 20 | void Car::Show(){ 21 | std::cout << "Show car called!" << std::endl; 22 | } 23 | 24 | int main() 25 | { 26 | std::unique_ptr ptr1 = std::make_unique(); 27 | ptr1->Show(); 28 | 29 | std::unique_ptr ptr2 = std::move(ptr1); 30 | if(!ptr1){ 31 | std::cout << "ptr1 is now null!\n"; 32 | } 33 | ptr2->Show(); 34 | 35 | return 0; 36 | 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /StaticDynamicCourse.md: -------------------------------------------------------------------------------- 1 | # Header Files (.h or .hpp) 2 | ### Purpose: Header files contain declarations of functions, classes, variables, and other constructs. They act as an interface that other files can include and use. 3 | ### Usage: Header files are typically included in source files (.cpp), allowing those source files to access the declarations inside the headers. 4 | ```cpp 5 | // mathutils.h 6 | #ifndef MATHUTILS_H 7 | #define MATHUTILS_H 8 | 9 | // Function declaration 10 | int add(int a, int b); 11 | int multiply(int a, int b); 12 | 13 | #endif 14 | ``` 15 | 16 | # 2. Source Files (.cpp or .c) 17 | ### Purpose: Source files contain the actual implementation (definitions) of functions, classes, and other constructs declared in header files. 18 | ### Usage: The .cpp file includes the header file and provides the definitions for the functions declared in the header. 19 | ```cpp 20 | // mathutils.cpp 21 | #include "mathutils.h" 22 | 23 | // Function definitions 24 | int add(int a, int b) { 25 | return a + b; 26 | } 27 | 28 | int multiply(int a, int b) { 29 | return a * b; 30 | } 31 | ``` 32 | # 3. Libraries 33 | Libraries are collections of precompiled code that you can reuse in your programs. There are two main types of libraries: 34 | 35 | ## 3.1 Static Libraries (.lib or .a on Linux) 36 | ### Purpose: Static libraries are linked directly into your executable at compile time. This means the code from the library is included in the final .exe or binary file. 37 | ### Usage: The code from a static library becomes part of your application, which makes the final application larger in size but independent of the library afterward. 38 | 39 | ## 3.2 Dynamic Libraries (DLLs in Windows, .so in Linux) 40 | ### Purpose: Dynamic libraries are linked at runtime, meaning they are separate files (like .dll in Windows) that the application uses during execution. The main advantage is smaller executable size and the ability to update the DLL without recompiling the whole application. 41 | ### Usage: The application loads the DLL at runtime and calls its functions. 42 | -------------------------------------------------------------------------------- /hackMe.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void softwareAccess() { 7 | cout << "Hello! Hope you're having a fantastic day!" << endl; 8 | 9 | // Password check 10 | string password = "ab5&"; 11 | string userInput; 12 | cout << "Enter the password to access the program: "; 13 | cin >> userInput; 14 | 15 | if (userInput == password) { 16 | cout << "Access granted!" << endl; 17 | } else { 18 | cout << "Access denied." << endl; 19 | } 20 | } 21 | 22 | int main() { 23 | softwareAccess(); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /modern C++/CPP14.md: -------------------------------------------------------------------------------- 1 | # C++14 2 | 3 | ## Overview 4 | Many of these descriptions and examples are taken from various resources (see [Acknowledgements](#acknowledgements) section) and summarized in my own words. 5 | 6 | C++14 includes the following new language features: 7 | - [binary literals](#binary-literals) 8 | - [generic lambda expressions](#generic-lambda-expressions) 9 | - [lambda capture initializers](#lambda-capture-initializers) 10 | - [return type deduction](#return-type-deduction) 11 | - [decltype(auto)](#decltypeauto) 12 | - [relaxing constraints on constexpr functions](#relaxing-constraints-on-constexpr-functions) 13 | - [variable templates](#variable-templates) 14 | - [\[\[deprecated\]\] attribute](#deprecated-attribute) 15 | 16 | C++14 includes the following new library features: 17 | - [user-defined literals for standard library types](#user-defined-literals-for-standard-library-types) 18 | - [compile-time integer sequences](#compile-time-integer-sequences) 19 | - [std::make_unique](#stdmake_unique) 20 | 21 | ## C++14 Language Features 22 | 23 | ### Binary literals 24 | Binary literals provide a convenient way to represent a base-2 number. 25 | It is possible to separate digits with `'`. 26 | ```c++ 27 | 0b110 // == 6 28 | 0b1111'1111 // == 255 29 | ``` 30 | 31 | ### Generic lambda expressions 32 | C++14 now allows the `auto` type-specifier in the parameter list, enabling polymorphic lambdas. 33 | ```c++ 34 | auto identity = [](auto x) { return x; }; 35 | int three = identity(3); // == 3 36 | std::string foo = identity("foo"); // == "foo" 37 | ``` 38 | 39 | ### Lambda capture initializers 40 | This allows creating lambda captures initialized with arbitrary expressions. The name given to the captured value does not need to be related to any variables in the enclosing scopes and introduces a new name inside the lambda body. The initializing expression is evaluated when the lambda is _created_ (not when it is _invoked_). 41 | ```c++ 42 | int factory(int i) { return i * 10; } 43 | auto f = [x = factory(2)] { return x; }; // returns 20 44 | 45 | auto generator = [x = 0] () mutable { 46 | // this would not compile without 'mutable' as we are modifying x on each call 47 | return x++; 48 | }; 49 | auto a = generator(); // == 0 50 | auto b = generator(); // == 1 51 | auto c = generator(); // == 2 52 | ``` 53 | Because it is now possible to _move_ (or _forward_) values into a lambda that could previously be only captured by copy or reference we can now capture move-only types in a lambda by value. Note that in the below example the `p` in the capture-list of `task2` on the left-hand-side of `=` is a new variable private to the lambda body and does not refer to the original `p`. 54 | ```c++ 55 | auto p = std::make_unique(1); 56 | 57 | auto task1 = [=] { *p = 5; }; // ERROR: std::unique_ptr cannot be copied 58 | // vs. 59 | auto task2 = [p = std::move(p)] { *p = 5; }; // OK: p is move-constructed into the closure object 60 | // the original p is empty after task2 is created 61 | ``` 62 | Using this reference-captures can have different names than the referenced variable. 63 | ```c++ 64 | auto x = 1; 65 | auto f = [&r = x, x = x * 10] { 66 | ++r; 67 | return r + x; 68 | }; 69 | f(); // sets x to 2 and returns 12 70 | ``` 71 | 72 | ### Return type deduction 73 | Using an `auto` return type in C++14, the compiler will attempt to deduce the type for you. With lambdas, you can now deduce its return type using `auto`, which makes returning a deduced reference or rvalue reference possible. 74 | ```c++ 75 | // Deduce return type as `int`. 76 | auto f(int i) { 77 | return i; 78 | } 79 | ``` 80 | ```c++ 81 | template 82 | auto& f(T& t) { 83 | return t; 84 | } 85 | 86 | // Returns a reference to a deduced type. 87 | auto g = [](auto& x) -> auto& { return f(x); }; 88 | int y = 123; 89 | int& z = g(y); // reference to `y` 90 | ``` 91 | 92 | ### decltype(auto) 93 | The `decltype(auto)` type-specifier also deduces a type like `auto` does. However, it deduces return types while keeping their references and cv-qualifiers, while `auto` will not. 94 | ```c++ 95 | const int x = 0; 96 | auto x1 = x; // int 97 | decltype(auto) x2 = x; // const int 98 | int y = 0; 99 | int& y1 = y; 100 | auto y2 = y1; // int 101 | decltype(auto) y3 = y1; // int& 102 | int&& z = 0; 103 | auto z1 = std::move(z); // int 104 | decltype(auto) z2 = std::move(z); // int&& 105 | ``` 106 | ```c++ 107 | // Note: Especially useful for generic code! 108 | 109 | // Return type is `int`. 110 | auto f(const int& i) { 111 | return i; 112 | } 113 | 114 | // Return type is `const int&`. 115 | decltype(auto) g(const int& i) { 116 | return i; 117 | } 118 | 119 | int x = 123; 120 | static_assert(std::is_same::value == 0); 121 | static_assert(std::is_same::value == 1); 122 | static_assert(std::is_same::value == 1); 123 | ``` 124 | 125 | See also: [`decltype (C++11)`](README.md#decltype). 126 | 127 | ### Relaxing constraints on constexpr functions 128 | In C++11, `constexpr` function bodies could only contain a very limited set of syntaxes, including (but not limited to): `typedef`s, `using`s, and a single `return` statement. In C++14, the set of allowable syntaxes expands greatly to include the most common syntax such as `if` statements, multiple `return`s, loops, etc. 129 | ```c++ 130 | constexpr int factorial(int n) { 131 | if (n <= 1) { 132 | return 1; 133 | } else { 134 | return n * factorial(n - 1); 135 | } 136 | } 137 | factorial(5); // == 120 138 | ``` 139 | 140 | ### Variable templates 141 | C++14 allows variables to be templated: 142 | 143 | ```c++ 144 | template 145 | constexpr T pi = T(3.1415926535897932385); 146 | template 147 | constexpr T e = T(2.7182818284590452353); 148 | ``` 149 | 150 | ### [[deprecated]] attribute 151 | C++14 introduces the `[[deprecated]]` attribute to indicate that a unit (function, class, etc.) is discouraged and likely yield compilation warnings. If a reason is provided, it will be included in the warnings. 152 | ```c++ 153 | [[deprecated]] 154 | void old_method(); 155 | [[deprecated("Use new_method instead")]] 156 | void legacy_method(); 157 | ``` 158 | 159 | ## C++14 Library Features 160 | 161 | ### User-defined literals for standard library types 162 | New user-defined literals for standard library types, including new built-in literals for `chrono` and `basic_string`. These can be `constexpr` meaning they can be used at compile-time. Some uses for these literals include compile-time integer parsing, binary literals, and imaginary number literals. 163 | ```c++ 164 | using namespace std::chrono_literals; 165 | auto day = 24h; 166 | day.count(); // == 24 167 | std::chrono::duration_cast(day).count(); // == 1440 168 | ``` 169 | 170 | ### Compile-time integer sequences 171 | The class template `std::integer_sequence` represents a compile-time sequence of integers. There are a few helpers built on top: 172 | * `std::make_integer_sequence` - creates a sequence of `0, ..., N - 1` with type `T`. 173 | * `std::index_sequence_for` - converts a template parameter pack into an integer sequence. 174 | 175 | Convert an array into a tuple: 176 | ```c++ 177 | template 178 | decltype(auto) a2t_impl(const Array& a, std::integer_sequence) { 179 | return std::make_tuple(a[I]...); 180 | } 181 | 182 | template> 183 | decltype(auto) a2t(const std::array& a) { 184 | return a2t_impl(a, Indices()); 185 | } 186 | ``` 187 | 188 | ### std::make_unique 189 | `std::make_unique` is the recommended way to create instances of `std::unique_ptr`s due to the following reasons: 190 | * Avoid having to use the `new` operator. 191 | * Prevents code repetition when specifying the underlying type the pointer shall hold. 192 | * Most importantly, it provides exception-safety. Suppose we were calling a function `foo` like so: 193 | ```c++ 194 | foo(std::unique_ptr{new T{}}, function_that_throws(), std::unique_ptr{new T{}}); 195 | ``` 196 | The compiler is free to call `new T{}`, then `function_that_throws()`, and so on... Since we have allocated data on the heap in the first construction of a `T`, we have introduced a leak here. With `std::make_unique`, we are given exception-safety: 197 | ```c++ 198 | foo(std::make_unique(), function_that_throws(), std::make_unique()); 199 | ``` 200 | 201 | See the section on [smart pointers (C++11)](README.md#smart-pointers) for more information on `std::unique_ptr` and `std::shared_ptr`. 202 | 203 | ## Acknowledgements 204 | * [cppreference](http://en.cppreference.com/w/cpp) - especially useful for finding examples and documentation of new library features. 205 | * [C++ Rvalue References Explained](http://thbecker.net/articles/rvalue_references/section_01.html) - a great introduction I used to understand rvalue references, perfect forwarding, and move semantics. 206 | * [clang](http://clang.llvm.org/cxx_status.html) and [gcc](https://gcc.gnu.org/projects/cxx-status.html)'s standards support pages. Also included here are the proposals for language/library features that I used to help find a description of, what it's meant to fix, and some examples. 207 | * [Compiler explorer](https://godbolt.org/) 208 | * [Scott Meyers' Effective Modern C++](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996) - highly recommended book! 209 | * [Jason Turner's C++ Weekly](https://www.youtube.com/channel/UCxHAlbZQNFU2LgEtiqd2Maw) - nice collection of C++-related videos. 210 | * [What can I do with a moved-from object?](http://stackoverflow.com/questions/7027523/what-can-i-do-with-a-moved-from-object) 211 | * [What are some uses of decltype(auto)?](http://stackoverflow.com/questions/24109737/what-are-some-uses-of-decltypeauto) 212 | * And many more SO posts I'm forgetting... 213 | 214 | ## Author 215 | Anthony Calandra 216 | 217 | ## Content Contributors 218 | See: https://github.com/AnthonyCalandra/modern-cpp-features/graphs/contributors 219 | 220 | ## License 221 | MIT 222 | -------------------------------------------------------------------------------- /modern C++/ModernC++.md: -------------------------------------------------------------------------------- 1 | # Reference Type 2 | ## When they were introduced? 3 | - Introduced in C++98 4 | ## What are reference types 5 | - Defines an alternative name for a variable (an alias) 6 | - It is created with the & operator during declaration 7 | - Always needs an initializer! 8 | - It can be used to modify a variable like pointer 9 | - A reference is NOT a new variable; it is just another name 10 | - They have both same memory address 11 | ## Why they were introduced? 12 | - safer because they must always refer to valid objects. 13 | ## Difference between a pointer & a reference 14 | - Reference : needs initializer, cannot be nullptr, boud to its referent, no storage required. 15 | - Pointer : no need for initializer, can be nullptr, can point other variables, has it's own storage. 16 | 17 | # Name mangling 18 | - Name mangling in C++ refers to the process by which the compiler modifies the names of functions, variables, or other identifiers to encode additional information about them 19 | ## Why is Mangling Needed? 20 | - In C (and similar languages), functions have unique names, so there's no ambiguity when linking them. However, C++ allows: 21 | - Function overloading: Multiple functions can have the same name but different parameter types. 22 | - Namespaces: Identifiers can be scoped inside different namespaces. 23 | - g++ -o myprogram myprogram.cpp -Wl,-Map=myprogram.map 24 | - nm is a Unix/Linux command-line utility used to display the symbol table of object file 25 | - nm myprogram | c++filt to demangle 26 | 27 | # Function Pointer 28 | - Pointer that holds the address of a function 29 | - The type is same as the signature of the function (return type & arguments) 30 | - Can be used to indirectly invoke a function even if the function name is not known 31 | - used by algorithms and classes for optimization 32 | - \ (*fnptr)args = &function 33 | 34 | # Default Copy Constructor (Shallow Copy) 35 | If you do not explicitly define a copy constructor, the C++ compiler provides a default copy constructor that performs a shallow copy. 36 | ## Example of Default Shallow Copy 37 | ```cpp 38 | class Shallow { 39 | public: 40 | int *data; 41 | 42 | Shallow(int value) { 43 | data = new int; 44 | *data = value; 45 | } 46 | }; 47 | 48 | int main() { 49 | Shallow obj1(10); 50 | Shallow obj2 = obj1; // Default copy constructor (shallow copy) 51 | 52 | // Both obj1.data and obj2.data point to the same memory 53 | *obj2.data = 20; 54 | 55 | // Now, obj1.data also reflects the change 56 | std::cout << *obj1.data; // Outputs: 20 57 | 58 | delete obj1.data; // Deleting data affects both obj1 and obj2 59 | return 0; 60 | } 61 | ``` 62 | ## Issues with Shallow Copy: 63 | - Shared Resources: Both objects share the same dynamically allocated memory. 64 | - Double Deletion: If both objects try to delete the same memory, it leads to undefined behavior. 65 | 66 | # Implementing a Deep Copy 67 | To perform a deep copy, you need to define your own copy constructor that allocates separate memory for the copied object and copies the actual data. 68 | ## Example of Deep Copy 69 | ```cpp 70 | class Deep { 71 | public: 72 | int *data; 73 | 74 | // Constructor 75 | Deep(int value) { 76 | data = new int; 77 | *data = value; 78 | } 79 | 80 | // Copy Constructor (Deep Copy) 81 | Deep(const Deep &other) { 82 | data = new int; // Allocate new memory 83 | *data = *(other.data); // Copy the value 84 | } 85 | 86 | // Destructor 87 | ~Deep() { 88 | delete data; 89 | } 90 | }; 91 | 92 | int main() { 93 | Deep obj1(10); 94 | Deep obj2 = obj1; // Calls deep copy constructor 95 | 96 | *obj2.data = 20; 97 | 98 | std::cout << *obj1.data; // Outputs: 10 99 | std::cout << *obj2.data; // Outputs: 20 100 | 101 | // No double deletion issue since obj1 and obj2 have separate memory 102 | return 0; 103 | } 104 | ``` 105 | ## When to Use Deep Copy 106 | Use a deep copy when your class manages resources that require ownership, such as: 107 | - Dynamic Memory Allocation: If your class allocates memory using new, malloc, etc. 108 | - File Handles or Network Connections: When your class manages resources like file descriptors, sockets, etc. 109 | - Complex Data Structures: When your class contains complex members that require independent copies. 110 | 111 | 112 | # Delegating Constructors (C++11) 113 | - Allows a constructor to call another constructor 114 | - Replacement for common initialization 115 | - Reduces duplicate initialization code in multiple constructors 116 | ```cpp 117 | #include 118 | #include 119 | 120 | class Person { 121 | private: 122 | std::string name; 123 | int age; 124 | 125 | public: 126 | // Constructor that takes both name and age 127 | Person(const std::string& name, int age) : name(name), age(age) { 128 | std::cout << "Person created with name and age\n"; 129 | } 130 | 131 | // Delegating constructor that only takes a name, assumes a default age 132 | Person(const std::string& name) : Person(name, 0) { // Delegates to the constructor above 133 | std::cout << "Person created with name only\n"; 134 | } 135 | 136 | // Delegating constructor that takes no arguments, assumes default values 137 | Person() : Person("Unknown", 0) { // Delegates to the constructor above 138 | std::cout << "Person created with no details\n"; 139 | } 140 | 141 | void display() const { 142 | std::cout << "Name: " << name << ", Age: " << age << '\n'; 143 | } 144 | }; 145 | 146 | int main() { 147 | Person p1("Alice", 25); // Calls the first constructor 148 | Person p2("Bob"); // Calls the second constructor, which delegates to the first 149 | Person p3; // Calls the third constructor, which delegates to the first 150 | 151 | p1.display(); 152 | p2.display(); 153 | p3.display(); 154 | 155 | return 0; 156 | } 157 | ``` 158 | 159 | # default & deleted (C++11) 160 | ```cpp 161 | #include 162 | 163 | class Example { 164 | public: 165 | // Constructor is explicitly defaulted 166 | Example() = default; 167 | 168 | // Copy constructor is deleted, preventing object copying 169 | Example(const Example&) = delete; 170 | 171 | // Assignment operator is also deleted 172 | Example& operator=(const Example&) = delete; 173 | 174 | void setValue(int a) {} 175 | void setValue(float) = delete; 176 | 177 | // Destructor is explicitly defaulted 178 | ~Example() = default; 179 | }; 180 | 181 | int main() { 182 | Example obj1; // This is allowed: default constructor is available. 183 | 184 | // Example obj2 = obj1; // Error: Copy constructor is deleted. 185 | // obj1 = obj2; // Error: Assignment operator is deleted. 186 | 187 | Example ex1; 188 | ex1.setValue(4); 189 | ex1.setValue(4.1); // will not be invoked! 190 | 191 | return 0; 192 | } 193 | ``` -------------------------------------------------------------------------------- /modern C++/range_loops.md: -------------------------------------------------------------------------------- 1 | - introduced in C++11 2 | - Syntax: for (auto element : container) where element iterates over each item in container. 3 | - Automatic Iteration: Iterates over each element in a container (like arrays, vectors, lists) without needing an index. 4 | - Read-Only or Modifiable: Use auto& element to modify the elements or const auto& element to keep them read-only. 5 | - Simplified Looping: Removes the need for size() or boundary conditions, making the code cleaner and easier to understand. 6 | -------------------------------------------------------------------------------- /modern C++/uniform_initialization.md: -------------------------------------------------------------------------------- 1 | Uniform initialization in C++ is a syntax introduced with C++11 to provide a consistent and uniform way to initialize variables and objects. It uses curly braces {} for initialization and helps reduce ambiguities, especially with constructors, providing clearer code. 2 | 3 | ### Key Features: 4 | 1 - Consistent Syntax: You can use {} to initialize variables of any type, including primitives, classes, arrays, and containers. 5 | 6 | ```cpp 7 | int x{10}; // Primitive type 8 | std::vector vec{1, 2, 3}; // Initializing a vector with values 9 | ``` 10 | 2 - Prevents Narrowing Conversions: One of the most important features of uniform initialization is that it prohibits "narrowing conversions" (where precision may be lost). 11 | ```cpp 12 | int a = 3.5; // Allowed in traditional initialization 13 | int b{3.5}; // Error in uniform initialization (narrowing) 14 | ``` 15 | 3 - Initialization of Aggregate Types: Structs and arrays can be initialized easily using uniform initialization. 16 | 17 | ```cpp 18 | struct Point { 19 | int x; 20 | int y; 21 | }; 22 | 23 | Point p{10, 20}; // Initializes p.x = 10, p.y = 20 24 | ``` 25 | 4 - Works with Constructors: If a class has a constructor, uniform initialization can be used to call that constructor. 26 | 27 | ```cpp 28 | class MyClass { 29 | public: 30 | MyClass(int a, int b) { /*...*/ } 31 | }; 32 | 33 | MyClass obj{1, 2}; // Calls MyClass(int, int) constructor 34 | ``` 35 | --------------------------------------------------------------------------------