Skip to content

onur-dogan/Cpp-Examples

Repository files navigation

Cpp-Examples

The C++ Project includes some examples and notes (mostly C++11). It also contains additional examples/notes from the C++ How to Program (9th Edition) book.

Notes

  • The main function is the designated start for program execution. All C++ programs must have a main function. If you try to compile a C++ program without a main function, the compiler raises an error. It can't be overloaded or declared an inline or static function. Also, it can't have its address taken, and can't be called from your program. It can be declared in different forms:
    1. int main() {...} which runs independently of environment-provided arguments.
    2. int main(int argc, char *argv[]) {...} which accepts environment provided arguments:
      • argc (Argument Count) argument is a non-negative integer that contains the count of arguments that follow in argv[]
      • argv[] (Argument Vector) argument is an array of null-terminated strings representing command-line arguments entered by the user of the program. By convention, argv[0] is the command with which the program is invoked. So, argv[0] displays the program filename. argv[1] is the first command-line argument. The last argument from the command line is argv[argc - 1], and argv[argc] is always NULL.
      • The size of the array pointed to by argv is at least argc + 1, and the last element, argv[argc], is guaranteed to be a NULL pointer:
    3. int main(/* implementation-defined */) {...} which accepts implementation-defined type parameters. The C++ standards recommend implementation-defined main functions to place the extra (optional) parameters after argv argument.
  • endl manipulator inserts a newline and flushes the stream.
  • Header files shouldn't include namespaces.
  • unsigned keyword allows the variable to be only a positive. The integer can never be a negative value.
  • default_random_engine - srand functions change the seed(starting point) of the random number generator algorithm.
  • float (4), long (4), double (8), long double (8)
  • Stack: LIFO, Queue: FIFO.
  • The ampersand(&) is used in variable declarations to declare reference variable.
  • Overloaded Function: Function overloading is a feature of OOP where the multiple functions with the same name has different parameter data types.
  • Temporary is a construct that generates an ordinary type or function at compile time based on arguments the user supplies for the template parameters. They are described as template <typename T> or template<class T>. typename and class keywords can be used interchangeably.
  • Performance Concern: If the performance is important, then better to avoid using recursion functions. It takes more time and uses more memory. The deeper the recursion, the more memory is used. Because each recursive call requires its own stack frame to store variables and other information.
  • vector.insert() and vector.emplace are used for the same purpose. However;
    • emplace constructs an object in place at a specified position, potentially avoiding a copy operation.
    • insert adds a copy of the object at the specified position.
  • std::vector::begin returns a read/write iterator that points to the first element in the vector.
  • std::vector::end returns a read/write iterator that points to the last element in the vector.
  • std::vector::cbegin returns a read-only iterator that points to the first element in the vector.
  • std::vector::crend returns a read-only reverse iterator that pointsto one before the first element in the vector.
  • std::vector::crbegin returns a read-only reverse iterator that points to the last element in the vector.
  • std::vector::cend returns a read-only iterator that points to the last element in the vector.
  • It is important to set a default value like nullptr to the pointers. It might cause critical issues to update a pointer that doesn't have a default value since the value might not point to a valid memory location.
  • lvalue simply means an object that has an identifiable location in memory.
  • r-value simply means, an object that has no identifiable location in memory.
  • char array constants have a static storage duration (they exist throughout the program).
  • The ~ operator is used to reverse operation on the bytes so it makes sense to use it for destructor function definitions like ~Destroy()
  • When a variable is declared as static, space for it gets allocated for the lifetime of the program. The space for the static variable is allocated only once.
  • A static variable of a class, gets allocated once so it stores one value for each generated same type class. So, it isn't used to store special values for each class. It stores the class specific global variables.
  • The static variable can't be defined with const since const keyword means that it can't change the objects in the function/class in which it is defined. However, the static variables are independent of the class objects
  • Objects are created from the inside out and destroyed from the outside in via destructor functions.
  • The friend class/function can access private and protected members of a class. The parameter object that references the class must be a constant.
    • friend functions in the class have permission to access any property(public/protected/private) of the class which it is defined
    • friend class have permission to access public/private/protected members of other classes in which it is declared as a friend
  • Using this-> is same with (*this).. Because the dot(.) operator is prioritized higher than the asterisk(*) operator, it is necessary to use parentheses.
  • The operators can be overloaded to customize some functionalities. It is like overloading the << operator to print a text specifically by the class requirements or the ++ operator to update a character in the text instead of increasing the number.
  • struct keyword allows us to create structures. Structures are a way to group several related variables into one place like an object and can contain different data types:
    struct str {
        int num;
        string text;
        ...
    }
  • A memory leak occurs when new memory is allocated dynamically and never deallocated. In C programs, new memory is allocated by the malloc or calloc functions, and deallocated by the free function. In C++, new memory is usually allocated by the new operator and deallocated by the delete or the delete [] operator. The list variables should be deallocated by the delete [] since it guarantees to call all of the elements in the list. Similarly, use delete to deallocate the memory that is defined as a single element. Using delete [] to deallocate the single memorized element is undefined.
  • friend functions can't be inherited in C++. If the base class has any friend function, this function doesn’t become the friend of the derived class.
  • Polymorphism means having multiple forms. To adapt polymorphism in inherited classes, override an inherited function in the derived class by defining a function with the same prototype of the overridden function and using override keyword.
  • When declaring a function with override keyword, the compiler checks whether the base class has the same function that has the same signature(same name, parameters). If it doesn't exist, then the compiler shows error. Also, the base class must be declared as a virtual function to enable dynamic overriding.
  • virtual functions cannot be static but can be a friend function of another class. Also, the constructors can't be defined as virtual cause virtual pointer doesn't define when the constructor of the class is executed.
  • About the difference between virtual and abstract functions, the virtual function must have a base functionality(body) so, it provides the derived classes with the option of overriding it. However, this is not mandatory. When it is not overridden, it uses the base function that is defined as default. However, the abstract function is defined without any functionality(body) as default so it has to be overridden by the (non-abstract) subclasses. This override process is mandatory unlike the virtual functions.
  • A namespace is a declarative region that provides a scope to the identifiers inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries. Code in header files should always use the fully qualified namespace name.
  • final specifier is used to prevent overriding of a virtual function.
  • If a class that is defined with a final specifier, can't be a base class. So, the classes with final specifier, don't allow inheritance.
  • For the inherited classes;
    • When an object of the derived class is created, the constructor of the base class executes first. Then, the constructor of the derived class executes. If there is a deeper inheritance hierarchy, then this flow executes in the same order (cascade).
    • In the opposite way, when the derived class's object is destroyed, the destructors are called in the reverse order of the constructors. So, the destructor function of the derived class executes first, followed by execution of the destructor of the base class.
  • mutable specifier is used to allow class members to be able to be modified even if the containing object is declared const.
  • One of the advantages of OOP is code reuse. There are two ways we can do code reuse either by the implementation of inheritance (is-a relationship), or object composition (has-a relationship)
    • A is-a relation is based on inheritance. For example, Car (derived) class has is-a relation with the Vehicle (base) class. In short, the Car class is a sub-class of Vehicle class, so it can be described similarly as Car class is a (subclass of) Vehicle class.
    • A has-a relation is based on composition. For example, Car class has has-a relation with the Wheel and Brakes classes. In short, Wheel and Brakes are parts of a Car, so it can be described similarly as Car has wheel and brakes.
  • typeid operator returns the runtime type information of the parameter like a data type. For a class defined variable, it returns the information of the class (e.g. typeid(...).name() returns the class name).
  • The typedef keyword is used to create customized data types with aliased names. For example;
    • istream type definition represents the basic_istream<char> template customization. typedef keyword is used like typedef basic_istream<char> istream;
    • ostream type definition represents the basic_istream<char> template customization. typedef keyword is used like typedef basic_ostream<char> ostream;
    • A customized pointer definition could be defined like typedef Person * personPtr;
    • A customized vector definition could be defined like typedef std::vector<Person> vPerson;
    • A customized vector pointer definition could be defined like typedef std::vector<Person *> vPersonPtr;
    • A customized function definition could be defined like typedef void (* personFunctionPtr)(std::char, int);
  • The string_view template specialization provides an efficient way to pass a read-only(constant), exception-safe, non-owning handle to the character data of any string. It is optimized for the constant string operations. For example, when declaring constant(enum) strings that shouldn't be modified anywhere, it is a good choice.
  • constexpr keyword improves program performance by computing at compile time rather than run time. Unlike const, constexpr can also be applied to functions and class constructors.
  • boolalpha manipulator formats and displays the boolean variables in text format (true for 1, and false for 0). Using noboolalpha manipulator disables this feature so it displays as 1 or 0 as in normal.
  • showpoint manipulator is used to show(fill) the zeros of the decimal value. So, the variable could be displayed in a certain length. For example, a float variable with the 2.300 value shows as 2.3 in normal. By setting the showpoint manipulator, it shows as 2.30000. Setting the precision function declares how many characters will be displayed in total, so the zeros could be limited. After setting setprecision(5), it shows as 2.3000. On the other hand, using the noshowpoint manipulator disables this feature, so the decimal point is only displayed for numbers whose decimal part is not zero as in normal.
  • scientific manipulator is used to display the numbers in scientific notations.
  • cin.fail() method is used to check whether the entered input type is the same as the variable type. If it's not in the same data type, it returns 1. Otherwise, returns 0.
  • The preprocessors are programs that process the source code before compilation. The preprocessor directives are special commands that are used to instruct the preprocessor. It begins with a # symbol and tells the preprocessor to the modify source code before compilation. Some predefined preprocessor macros:
    • __FILE__ preprocessor macro expands to the name of the current input file, in the form of a C string constant. This is the path by which the preprocessor opened the file, not the short name specified in ‘#include’ or as the input file name argument.
    • __LINE__ preprocessor macro expands to the current input line number, in the form of a decimal integer constant. While we call it a predefined macro, it’s a pretty strange macro, since its “definition” changes with each new line of source code.
    • __DATE__ preprocessor macro expands to a string constant that describes the date on which the preprocessor is being run. The string constant contains eleven characters and looks like "Dec 14 2024". If the day of the month is less than 10, it is padded with a space on the left. If GCC cannot determine the current date, it will emit a warning message (once per compilation) and __DATE__ will expand to "??? ?? ????".
    • __TIME__ preprocessor macro expands to a string constant that describes the time at which the preprocessor is being run. The string constant contains eight characters and looks like "00:30:10". If GCC cannot determine the current time, it will emit a warning message (once per compilation) and __TIME__ will expand to "??:??:??".
    • __STDC__ preprocessor macro expands to the constant 1, to signify that this compiler conforms to ISO Standard C. If GNU CPP is used with a compiler other than GCC, this is not necessarily true. However, the preprocessor always conforms to the standard unless the -traditional-cpp option is used. This macro is not defined if the -traditional-cpp option is used.
    • __cplusplus preprocessor macro is defined when the C++ compiler is in use. It can be used to test whether a header is compiled by a C or a C++ compiler. This macro is similar to __STDC_VERSION__, in that it expands to a version number. Depending on the language standard selected, the value of the macro is 199711L for the 1998 C++ standard, 201103L for the 2011 C++ standard, 201402L for the 2014 C++ standard, 201703L for the 2017 C++ standard, 202002L for the 2020 C++ standard, 202302L for the 2023 C++ standard, or an unspecified value strictly larger than 202302L for the experimental languages enabled by -std=c++26 and -std=gnu++26.
    • __OBJC__ preprocessor macro is defined with value 1, when the Objective-C compiler is in use. __OBJC__ can be used to test whether a header is compiled by a C or an Objective-C compiler.
    • __ASSEMBLER__ preprocessor macro is defined with value 1 when preprocessing assembly language.
  • #define preprocessor directive is used to define a macro(symbolic constant). Macros are a way to represent a fragment of code or a symbolic constant value by giving it a name. When the preprocessor encounters the macro name in the code, it replaces it with the corresponding code fragment or value that is defined using the #define preprocessor. The symbolic constants(macros) do not take up memory space, they don't store anywhere.
  • std::ofstream (Output File Stream) is used to write into files. std::ifstream (Input File Stream) is used to read the data from a file.
  • std::ios is a base class for all stream classes using narrow char characters. Both this class and its parent class ios_base, define the components of streams that do not depend on whether the stream is an input or an output stream.
  • std::ios::app writes the new lines to the end of the file. So, the previous data in the file remains.
  • std::ios::out opens file for writing and deletes the previous data in the file. It writes the new data instead.
  • std::ios::in opens file for reading and allows inputs from the stream to get the data in the file.
  • std::ios::binary opens the file in binary mode.
  • Iterators are used to access and iterate through elements of data structures. std::istream_iterator provides input iterator semantics for streams. std::ostream_iterator provides output iterator semantics for streams.
  • std::splice carries the elements of the list to the other one and purges the elements from the main list.
  • std::merge carries the elements of the list to the other one as sorted and purges the elements from the main list.
  • std::unique removes the duplicates.
  • std::remove removes the element in the list equal to value(parameter).
  • std::priority_queue sorts the elements automatically and locates the biggest value to the top(front) of the queue. It is available to sort it descending and locate the lowers value to the top(front) by settings the 3.(_Compare) parameter. The default of it is less. The other options are: equal_to, not_equal_to, greater, greater_equal, less_equal.
  • equal_range function returns a std::pair containing a pair of iterators as pair::first and pair::second.
    • The pair::first value is the same as the upper_bound function returns. upper_bound is a built-in function used to find the first element in a sorted range that is strictly greater than a given value.
    • The pair::second value is the same as the lower_bound function returns. lower_bound is a built-in function used to find the position of an element in a sorted range that has a value not less than the given value.
  • std::bitset represents a fixed-size sequence of N bits(each bit occupies 1 bit of memory).
    • set() sets a given bit(1 or 0) to a particular value.
    • flips() toggles every bit to its opposite value(1 to 0, 0 to 1).
    • reset() sets every bit to false(0).
    • size() returns the total number of bits.
    • count() returns the number of bits which are set(1).
    • any() checks whether any of the bits are on(1) and returns true if all the bits are set as 1. Otherwise, returns false.
    • all() checks whether all of the bits are on(1) and returns true if all the bits are set as 1. Otherwise, returns false.
    • none() checks whether any of the bits are on(1) and returns true if none of the bits are set as 1. Otherwise, returns false.
    • test() checks the value of a bit and returns value at position. Returns 1 if the value is 1. Otherwise, returns 0.
    • bit1 &= bit2 performs binary logical AND operator and sets result into the bit1.
    • bit1 |= bit2 performs binary logical OR operator and sets result into the bit1.
    • bit1 ^= bit2 performs binary logical XOR operator and sets result into the bit1.
    • ~bit1 performs binary logical NOT operator and flips the bits to opposite (1 to 0 or 0 to 1).
    • >>= shifts the bits N step right.
    • <<= shifts the bits N step left.
    • to_string() converts bits to a string.
    • to_ulong() returns a numerical interpretation (the integral equivalent of the bits) of the bitset by converting the bitset to an unsigned long.
  • The header <algorithm> defines a collection of functions especially designed to be used on ranges of elements. Some functions in <algorithm>:
    • equal function compares whether the values are equal.
    • mismatch function returns a pair of iterators. The pair's first iterator is the first array's unmatched first value. The pair's second iterator is the unmatched first value in the second array.
    • remove function removes all elements equal to the value(parameter).
    • remove_copy function removes all elements equal to the value(parameter) and copies new sequence to the other one.
    • remove_if function removes elements for which predicate function returns true.
    • remove_copy_if function removes elements for which predicate function returns true and copies new sequence to the other one.
    • replace function replaces each element of one value with another value.
    • replace_copy function replaces each element of one value with another value and copies new sequence to the other one.
    • replace_if function replaces each element for which a predicate returns true with another value.
    • replace_copy_if function replaces each element for which a predicate returns true with another value and copies new sequence to the other one.
  • Notes of some mathematical algorithm functions:
    • fill_n function is used to fill the N elements with a given default value.
    • random_shuffle randomly shuffle the elements of a sequence.
    • count counts the number of copies of a value in a sequence.
    • count_if counts the elements of a sequence for which a predicate is true.
    • minmax_element return a pair of iterators pointing to the minimum and maximum elements in a range. first ==> min value, second ==> max value
      • min_element returns the minimum element in the range.
      • min returns the minimum value.
      • max_element returns the maximum element in the range.
      • max returns the maximum value.
    • accumulate accumulates values in the range.
    • for_each applies a function to every element of a sequence.
    • transform function performs an operation to all elements in the array and, transforms the new elements to a new array.
    • find_if finds the first element in a sequence for which a predicate is true.
    • find_if_not finds the first element in a sequence for which a predicate is false.
    • binary_search searches the value in the array and returns bool whether the value is in the array.
    • all_of checks whether the predicate function returns true for all of the elements.
    • any_of checks whether the predicate function returns true for any of the elements.
    • none_of checks whether the predicate function returns false for all of the elements.
    • swap swaps the elements with the each other.
    • iter_swap uses iterator to swap the elements with the each other by the indexes.
    • swap_ranges swaps each element in the range with the corresponding element in the range. The ranges must not overlap.
    • unique_copy removes the consecutive duplicate values and copies result to a sequence.
    • unique removes the consecutive duplicate values from the related array.
    • copy_backward copies the elements to the other sequence. It has the same effect as copy, but starts at the end of the range and works its way to the start, returning the start of the result.
    • merge merges two sorted ranges in one.
    • reverse reverses the sequence.
    • includes checks whether a sequence is a subsequence of the other one. It returns true if the sequence elements include the other sequence's elements.
    • set_difference returns the difference of two sorted ranges.
    • set_intersection returns the intersected elements of two sorted ranges.
    • set_symmetric_difference returns the symmetric difference(The values which are in the array and not in merged array, or in merged array and not in main array) of two sorted ranges.
    • set_union returns the union(The values which exist in one or both of the sequences) of two sorted ranges.
    • equal_range finds the lower and upper bound values and returns them as a pair.
      • lower_bound finds the first value that is lower than or equal to the value.
      • upper_bound finds the first value that is upper than the value.
    • is_heap function determines whether the any elements in the range is a heap.
    • is_heap_until searchs the end of a heap and returns an iterator pointing to the first element not in the heap.
    • make_heap constructs a heap in the range of the array.
    • sort_heap sort the elements in the heap.
  • lambda expressions are a convenient way of defining an anonymous function object (a closure) right at the location where it's invoked or passed as an argument to a function. Typically lambdas are used to encapsulate a few lines of code that are passed to algorithms or asynchronous functions.
  • noexcept expression specifies whether a function could throw exceptions. It is a suffix to a function declaration that represents a set of types that might be matched by an exception handler for any exception that exits a function.
  • set_new_handler takes a replacement handler as the argument, returns the previous handler. The newly configured handler function is the function called by allocation functions whenever a memory allocation attempt fails. It transfers control to your error-handling mechanism if the new operator fails to allocate memory. So, it allows us to catch and manage the memory allocation issues.
  • overflow_error specifies the arithmetic overflow errors for the situations in which a result of an arithmetic computation is too large for the destination type.
  • underflow_error specifies the arithmetic underflow errors for the situations in which the result of an arithmetic computation is less than the smallest value that can be stored in the computer.
  • abort function aborts the execution and generate a core-dump.
  • unique_ptr is a smart pointer that automatically manages the dynamically allocated resources on the heap via a pointer.
    • A unique pointer can point to only one resource(a single object or dynamically allocated array of objects).
    • A unique_ptr can transfer the ownership of the managed object to another unique_ptr if it's not declared as const.
    • A unique_ptr variable is created by using the new keyword, so it allocates dynamically. So, it must be freed by using the delete keyword. As the name suggests, the unique pointers free the dynamically allocated resource memory automatically when the destructor function is called, so it avoids the dynamically allocated resource memory issues.
  • The last pointer of the linked data structure must point to a NULL pointer to mark the end of the list. Each node is connected with the next one and the last node doesn't have any node after itself so it can't point to other next node.
  • Defining Dynamic Memory Allocation for the data structures that grow and shrink, saves memory.
  • size_t is a unsigned data type that only represents non-negative values.
  • Some string functions:
    • substr function constructs and returns a new string using the n characters starting at a position.
    • compare function compares the value of the string objects and returns an integer.
    • insert function inserts value of a string by starting at a position. If adding characters causes the length to exceed max_size(), length_error is thrown.
    • replace function removes the characters in a range from the string. In place, the characters of the other string would be inserted.
    • copy function copies substring into the string.
    • c_str function returns a const pointer to null-terminated content. This is a handle to internal data so shouldn't be modified.
    • data function returns a non-const pointer to contents. This is a pointer to the character sequence held by the string. Modifying the characters in the sequence is allowed.
    • istringstream is a class for input memory streams that stream the string into different variables.
    • ostringstream is a class for output memory streams. It effectively stores an instance of basic_string and performs output operations to it.
    • stoi function converts a string to an integer value.
    • stol function converts a string to a long value.
    • stoul function converts a string to an unsigned long value.
    • stoll function converts a string to a long long value.
    • stoull function converts a string to an unsigned long long value.
    • stof function converts a string to a float value.
    • stod function converts a string to a double value.
    • stold function converts a string to a long double value.
    • strtod function converts a string to a floating-point number. It returns the converted floating-point value and sets the string part to char pointer.
    • strtol function converts a string to a long integer. It returns the converted long integer and sets the string part to a char pointer.
    • strtoul function converts a string to a unsigned long integer. It returns the converted unsigned long integer and sets the string part to a char pointer.
  • C string is stored as an array of characters. C does not have a string type to create a string value. Instead, uses char[] type to create an array of characters to create a string value.
  • strcpy function copies the C string pointed by the source into the array pointed by the destination, including the terminating null character.
  • strncpy function copies N of the characters of the source to the array pointed by the destination.
  • strchr function finds the occurrence of a character in a string.
  • strpbrk function finds the first matched character of the search text in the text and returns the pointer to the first character of the search text found in the text. If there is no match, it returns NULL.
  • memcpy copies N bytes from one memory location to the other memory location regardless of the type of data stored. It is meant to be the fastest library routine for memory-to-memory copy.
  • memcmp compares the first num bytes of the block of memory pointed by a pointer to the first num bytes pointed by other pointer. Returning 0 if they all match or a value different from zero representing which is greater if they do not.
  • memmove copies N bytes of the source string to the destination string, guaranteeing correct behavior for overlapping strings.
  • const_cast operator is used to cast away the constness of variables. It configures a constant(const) variable as a non-const variable.
  • Notes of CMake commands:
    • cmake_minimum_required sets the minimum required version of cmake for a project. Also updates the policy settings.
    • project sets the name of the project, and stores it in the variable PROJECT_NAME. When called from the top-level CMakeLists.txt also stores the project name in the variable CMAKE_PROJECT_NAME.
    • set sets a normal, cache, or environment variable to a given value.
      • Setting normal value: set(<variable> <value>... [PARENT_SCOPE]). It sets or unsets <variable> in the current function or directory scope. If at least one <value>... is given, it sets the variable to that value. Otherwise, it unsets the variable. This is equivalent to unset(<variable>).
      • Setting cache entry: set(<variable> <value>... CACHE <type> <docstring> [FORCE]). It sets the given cache <variable> (cache entry). Since cache entries are meant to provide user-settable values this does not overwrite existing cache entries by default. Use the FORCE option to overwrite existing entries.
      • Setting environment variable: set(ENV{<variable>} [<value>]). It sets an environment variable to the given value. Subsequent calls of $ENV{<variable>} will return this new value.
    • add_executable adds an executable to the project using the specified source files.
    • add_library adds a library to the project using the specified source files.
      • Setting normal libraries like add_library(<name> [<type>] [EXCLUDE_FROM_ALL] <sources>...) add a library target called <name> to be built from the source files listed in the command invocation. The optional <type> specifies the type of library to be created:
        • STATIC: An archive of object files for use when linking other targets.
        • SHARED: A dynamic library that may be linked by other targets and loaded at runtime.
        • MODULE: A plugin that may not be linked by other targets, but may be dynamically loaded at runtime using dlopen-like functionality.
      • If no <type> is given the default is STATIC or SHARED based on the value of the BUILD_SHARED_LIBS variable. The options are:
        • EXCLUDE_FROM_ALL sets the EXCLUDE_FROM_ALL target property automatically.
    • target_compile_features adds expected compiler features to a target like target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])

About

C++ Notes and Examples

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published