C++

From HaFrWiki42
Jump to navigation Jump to search

Introduction

My favo(u)rite program C++ is not one of the easiest language to master.
Let me start with one of the most not understood parts.

Pointers, Values and Addresses

Usage Coding Output

For a C++ program, the memory of a computer is like a succession of memory cells, each one byte in size, and each with a unique address.
These single-byte memory cells are ordered in a way that allows data representations larger than one byte to occupy memory cells that have consecutive addresses.

The address of a variable can be obtained by preceding the name of a variable with an ampersand sign (&), known as address-of operator.
For example:

foo = &myvar;

assigns the address of variable myvar to foo; by preceding the name of the variable myvar with the address-of operator (&), we are no longer assigning the content of the variable itself to foo, but its address.

// my first pointer
#include <iostream>
using namespace std;

int main () {
  int firstvalue, secondvalue;
  int * mypointer;

  mypointer = &firstvalue;
  *mypointer = 10;
  mypointer = &secondvalue;
  *mypointer = 20;
  cout << "firstvalue is " << firstvalue << '\n';
  cout << "secondvalue is " << secondvalue << '\n';
  return 0;
}
firstvalue is 10
secondvalue is 20

Parsing

The examples are taken from Geeks for Geeks, C++ pointers and other pages on that website.

Passing by Value

Usage Coding Output

Call by value is used in certain conditions like:

  • When you do not want to change the actual parameters of the function.
  • When you want to make copies of the data instead of the actual data.
  • When space is not an issue.
  • Usually, when you do not deal with recursion or backtracking.
// C++ Program to implement
// Swapping using Call by function
#include <iostream>
using namespace std;

// Swap function to demonstrate
// call by value method
void swap(int x, int y)
{
    int t = x;
    x = y;
    y = t;
    cout << "After Swapping in function x: " << x
         << ", y: " << y << endl;
}

// Driver Code
int main()
{
    int x = 1, y = 2;

    cout << "Before Swapping: ";
    cout << "x: " << x << ", y: " << y << endl;

    swap(x, y);

    cout << "After Swapping: ";
    cout << "x: " << x << ", y: " << y << endl;

    return 0;
}

The output:

Before Swapping: 
x: 1, y: 2
After Swapping in function x:2, y:1
After Swapping: 
x: 1, y: 2

Passing by Pointer

Usage Coding Output

Here, the memory location (address) of the variables is passed to the parameters in the function, and then the operations are performed. It is also called the call by pointer method.

// C++ program to swap two numbers using
// pass by pointer
#include <iostream>
using namespace std;

void swap(int *x, int *y)
{
    int z = *x;
    *x = *y;
    *y = z;
}

// Driver Code
int main()
{
    int a = 45, b = 35;
    cout << "Before Swap\n";
    cout << "a = " << a << " b = " << b << "\n";

    swap(&a, &b);

    cout << "After Swap with pass by pointer\n";
    cout << "a = " << a << " b = " << b << "\n";
}
Before Swap
a = 45 b = 35
After Swap with pass by pointer
a = 35 b = 45

Passing by Reference

Usage Coding Output

It allows a function to modify a variable without having to create a copy of it. We have to declare reference variables. The memory location of the passed variable and parameter is the same and therefore, any change to the parameter reflects in the variable as well.

// C++ program to swap two numbers using
// pass by reference
#include <iostream>
using namespace std;
void swap(int& x, int& y)
{
    int z = x;
    x = y;
    y = z;
}

int main()
{
    int a = 45, b = 35;
    cout << "Before Swap\n";
    cout << "a = " << a << " b = " << b << "\n";

    swap(a, b);

    cout << "After Swap with pass by reference\n";
    cout << "a = " << a << " b = " << b << "\n";
}
Before Swap
a = 45 b = 35
After Swap with pass by reference
a = 35 b = 45

Pass by Pointer vs Pass by Reference

Knowing the differences between passing by pointer and passing by reference is crucial for effective function design.
The following table lists the major differences between the pass-by-pointer and pass-by-reference methods.

Parameters Pass by Pointer Pass by Reference
Passing Arguments We pass the address of arguments in the function call. We pass the arguments in the function call.
Accessing Values The value of the arguments is accessed via the dereferencing operator * The reference name can be used to implicitly reference a value.
Reassignment Passed parameters can be moved/reassigned to a different memory location. Parameters can’t be moved/reassigned to another memory address.
Allowed Values Pointers can contain a NULL value, so a passed argument may point to a NULL or even a garbage value. References cannot contain a NULL value, so it is guaranteed to have some value.

Strings

In C++, we can store the sequence of characters i.e. string in two ways:

  • either as a char array.
  • either as a std::string object.

In this paragraph, we will discuss some major differences between string and char[] in C++.

char str[14] = "GeeksforGeeks" string str("GfG is best");
// C++ Program to show the use of character array type strings
#include <iostream>
using namespace std;

int main()
{
    // Character array
    char str[14] = "GeeksforGeeks";

    // Print each character in the array
    for (int i = 0; i < 13; i++) {
        cout << str[i];
    }

    return 0;
}
// C++ Program to show the use of std::string
#include <iostream>
using namespace std;

int main()
{
    // Sample string
    string str("GFG is best");

    // Print the string
    cout << str;

    return 0;
}

Of course there are ways to convert one with the other.
But the usage can be rather strange for the beginner.

Online Reference

  • CppReference, Standard for modern C++ documentation
    • Up-to-date (C++11 t/m C++23)
    • Complete, all standard libraries and Language elements.
    • Good explanation.
  • Modernes Cpp, Blog and tutorials around Modern C++.
    • Clear explanation of modern features such as auto, constexpr, concepts, ranges, coroutines, etc.
    • Focused on practical use of modern C++.
    • Ideal for: C++ developers who already have some experience, but want to learn modern idioms.
  • CppInsights.io, Live visualisation of C++-code
    • Beginner and intermediate friendly.
    • Recently updated for C++17/C++20.
    • Clearly structured explanations with examples.
    • Recommended if you want to refresh your C++ skills with explanations rather than dry documentation.
  • GodBolt.org, Learningplatform for C++ (include Modern C++).
    • You can test C++ code and directly compare assembler output or other compilers.
    • Combine with cppreference to try out features directly.
    • Definitely do this for template debugging or performance tuning.

STL Container Maps & Sets

The C++ standard library (STL) offers more containers than vector and list.

STL container Map & sets
But what is a container?


You can find the definition of an STL container in all of the sources above. Here we will just give an informal definition.
An STL container

  • Has a sequence of elements [begin():end()).
  • Provides copy operations that copy all elements.
  • Provides move operations that move all elements.
  • Names its element type value_type.
  • Has iterator types called iterator and const_iterator.
  • Iterators provide &asteriks; ++ (both prefix and postfix), ==, and != with the appropriate semantics.
  • The iterators for list also provide −− for moving backward in the sequence; that’s called a bidirectional iterator.
  • The iterators for vector also provide −−, [], +, and − and are called random-access iterators (§20.7.1).
  • Provides insert() and erase(), front() and back(), push_back() and pop_back(), size(), swap(), etc.;
    vector and map also provide subscripting (e.g., operator []).
  • Provides comparison operators (==, !=, <, <=, >, and >=) that compare the elements.
  • Containers use lexicographical ordering for <, <=, >, and >=; that is, they compare their elements in order starting with the first.
Associative containers
Name Description
deque A cross between a list and a vector; don’t use until you have expert-level knowledge of algorithms and machine architecture.
forward_list A singly-linked list; use for lists that are mostly empty.
list A doubly-linked list; use when you need to insert and delete elements without moving existing elements.
map An ordered container of (key, value) pairs.
set An ordered container of keys.
unordered_map An unordered container of (key, value) pairs
unordered_set An unordered container of keys.
multimap A map where a key can occur multiple times.
multiset A set where a key can occur multiple times.
unordered_multimap An unordered_map where a key can occur multiple times.
unordered_multiset An unordered_set where a key can occur multiple times.
vector A contiguously allocated sequence of elements; use it as the default container.



Maps Sets
Maps are associative list, meaning a key, value pair.

Syntax

map<label_key,key_value> var_name 
  • label_key: data_type for the key
  • key_value: data type for the value
  • var_name: name of the variable

Examples

map<string, int> words;

Loop for pairs

Sets in C++ are containers that store unique elements in a sorted manner. The elements inside the set cannot be changed, once they are added to the set, they can only be inserted or deleted. They are implemented as BST (Binary Search Trees) in memory. Set is present in #include<set> header file. The elements inside the set can be accessed using iterators.

Syntax

set <data_type> name = {initial_values};
  • data_type: data type of the elements to be stored inside the set
  • initial_values: optional parameter which initializes the set with the given values

Note: By default the set stores values in non-decreasing order. To store the values in non-increasing order, we use an inbuilt comparator function

set <data_type, greater <data_type>> name; 

Examples

set <int> s; //initializes a set of size 0 which stores integer values arranged in non-decreasing order
set <int> s = {10, 20, 30}; //initializes a set having initial values as 10,20,30
set <int, greater <int>> s; //initializes a set of size 0 which stores integer values arranged in non-increasing order

Iterator

Name Description
input iterator Can iterate forward using ++ and read element values using *. This is the kind of iterator that istream offers; (BS - §20.6.4).

If (*p).m is valid, p−>m can be used as a shorthand.

output iterator Can iterate forward using ++ and write element values using *. This is the kind of iterator that ostream offers; (BS - 20.6.4).
forward iterator An input iterator that can iterate repeatedly over a sequence and repeatedly read from or write to an element. This is the kind of iterator that forward_list offers §20.6
bidirectional iterator A bidirectional iterator that can move forward and backwards n positions using +=n, +, −=n, and −.
contiguous iterator A random-access iterator where the elements are allocated contiguously. This is the kind of iterator that vector offers.

From the operations offered, we can see that wherever we can use an output iterator or an input iterator, we can use a forward iterator. A bidirectional iterator is also a forward iterator, and a random-access iterator is also a bidirectional iterator. |}

Class Rules

Rule of Three

The Rule of Three [1][2] says that there are three member functions that go together:

  1. the destructor,
  2. the copy constructor, and
  3. the assignment operator.

A class that defines a destructor should almost always define the other two members.
Moreover, a class that defines a copy constructor or assignment operator should usually define the other two members as well [3].

Rule of Five

The rule of thumb [4] (also known as the Rule of Five) for class special member functions is that if you explicitly define

  • any
    1. copy constructor,
    2. move constructor,
    3. copy assignment operator,
    4. move assignment operator, or
    5. destructor,

then

  • you must either explicitly define or default all of them.

Bancila, Marius. Modern C++ Programming Cookbook: Master Modern C++ with comprehensive solutions for C++23 and all previous standards (p. 159). (Function). Kindle Edition.

Rule of Zero

Opposed to the Rule of Five [4] on the one hand but complementing it on the other is the so-called Rule of Zero.
This rule states that unless a class deals with ownership of resources, it should have no custom destructors, copy and move constructors, and, respectively, copy and move assignment operators.

See also

top

RAII

  • Stroustrup, Why does C++ does not have a finally. Well, because of RAII.
  • SonarSource Blog, What are the Rules of Three, Five and Zero in C++?
  • Wikipedia, RAII - Resource Acquisition Is Initialization.

Reference

top

  1. DrDobbs, C-made-easier, the Rule of Three.
  2. Marshall Cline coined the term in 1991.
  3. Classes often have an empty virtual destructor, which is there only because it is virtual and not to do any actual work. Such destructors don’t count for the purpose of this discussion.
  4. 4.0 4.1 Bancila, Marius. Modern C++ Programming Cookbook: Master Modern C++ with comprehensive solutions for C++23 and all previous standards