C++ pointer from beginner to advanced

Introduction to C++ pointers

#include <iostream>

using namespace std;

int main() {
    
    
    int n = 5;
    cout << n << endl;
    cout << &n << endl;  // address of n

    int *ptr = &n;
    cout << ptr << endl;
    cout << *ptr << endl;

    *ptr = 10;
    cout << *ptr << endl;
    cout << n << endl;  // 10


    /* pointer should be initialized before deference
    int *ptr1;
    *ptr1 = 6;  // Variable 'ptr1' is uninitialized when used here
    */

    int v;
    int *ptr2 = &v;
    *ptr2 = 6;          // deference pointer
    cout << "v=" << v << endl;  // 6

    return 0;
}

What is a void pointer?

#include <iostream>

using namespace std;

void printNumber(int *numberPtr) {
    
    
    cout << *numberPtr << endl;
}

void printLetter(char *letterPtr) {
    
    
    cout << *letterPtr << endl;
}

// void pointer can point to any data type
void print(void *ptr, char data_type) {
    
    
    switch (data_type) {
    
    
        case 'i':
            cout << *((int *) ptr) << endl;  // cast void pointer into an int pointer
            break;
        case 'c':
            cout << *((char *) ptr) << endl;
// be careful when using void pointer, compiler don't know you are making an error or not in this particular situation:
//            cout << *((float *) ptr) << endl;
            break;
        default:
            cout << *((double *) ptr) << endl;
    }
}

int main() {
    
    
    int number = 1;
    printNumber(&number);
    char letter = 'a';
    printLetter(&letter);

    print(&number, 'i');
    print(&letter, 'c');

    return 0;
}

How to use pointers and arrays

#include <iostream>

using namespace std;

void test1() {
    
    
    int luckyNumbers[5] = {
    
    1, 2, 3, 4, 5};
    cout << &luckyNumbers[0] << endl;  // 012FF704  // address of first element
    cout << &luckyNumbers[1] << endl;  // 0083FD08
    cout << &luckyNumbers[2] << endl;  // 0083FD0C

    cout << endl;
    cout << luckyNumbers << endl;      // 012FF704  // address of first element
    cout << luckyNumbers + 1 << endl;  // 012FF708
    cout << luckyNumbers + 2 << endl;  // 012FF70C

    cout << endl;
    cout << *(luckyNumbers + 1) << endl;  // 2
    cout << *(luckyNumbers + 2) << endl;  // 3
}

int main() {
    
    
//    test1();

    int luckyNumbers[5];
    for (int i = 0; i < 5; ++i) {
    
    
        cout << "Number: ";
        cin >> luckyNumbers[i];
    }

    for (int i = 0; i < 5; ++i) {
    
    
        cout << *(luckyNumbers + i) << " ";
    }

    /* if change iteration to 6, we will get a junk number, so be careful when iterating through array or using pointer
    for (int i = 0; i < 6; ++i) {
        cout << *(luckyNumbers + i) << " ";
    }
    1 2 3 4 5 -858993460
    */
}

Return multiple values from a function using pointers?

#include <iostream>

using namespace std;

int getMin(const int numbers[], int size) {
    
    
    int min = numbers[0];
    for (int i = 1; i < size; ++i) {
    
    
        if (numbers[i] < min) {
    
    
            min = numbers[i];
        }
    }
    return min;
}

int getMax(const int numbers[], int size) {
    
    
    int max = numbers[0];
    for (int i = 1; i < size; ++i) {
    
    
        if (numbers[i] > max) {
    
    
            max = numbers[i];
        }
    }
    return max;
}

// using pointer to return multiple value from a function
void getMinMax(const int numbers[], int size, int *min, int *max) {
    
    
    for (int i = 1; i < size; ++i) {
    
    
        if (numbers[i] > *max) {
    
    
            *max = numbers[i];
        }
        if (numbers[i] < *min) {
    
    
            *min = numbers[i];
        }
    }
}

int main() {
    
    
    int numbers[5] = {
    
    1, 3, -2, 10, 28};
    cout << "min is " << getMin(numbers, 5) << endl;
    cout << "max is " << getMax(numbers, 5) << endl;

    int min = numbers[0], max = numbers[0];
    getMinMax(numbers, 5, &min, &max);
    cout << "min is " << min << " " << "max is " << max << endl;
    return 0;
}

Dynamic arrays - How to create/change arrays at runtime?

// Dynamic arrays
#include <iostream>

using namespace std;

/*
 * we want to achieve some situations such as below:
    int size;
    cin >> size;
    int myArray[size];

   however, the size of the array had to be constant, which means that
   the size of the array had to be known before we started our program.

   we can use dynamic array as a solution. For example:
   new keyword allocates memory: an array of specific size by user,
   and that address of the first element of array is stored in this myArray pointer.
 */

int main() {
    
    
    int size;
    cout << "Size: ";
    cin >> size;

    int *myArray = new int[size];

    for (int i = 0; i < size; ++i) {
    
    
        cout << "myArray[" << i << "]: ";
        cin >> myArray[i];
    }

    for (int i = 0; i < size; ++i) {
    
    
//        cout << myArray[i] << " ";
        cout << *(myArray + i) << " ";
    }

    delete[] myArray;  // deallocate memory
    myArray = nullptr;

    return 0;
}

Two-dimensional dynamic array

#include <iostream>

using namespace std;

int main() {
    
    
    int rows = 3, cols = 5;

    int **table = new int *[rows];  // pointer to pointer, create a new interger array of pointers

    for (int i = 0; i < rows; ++i) {
    
      // for each element, create a separate dynamic array
        table[i] = new int[cols];
    }

    table[1][2] = 100;  // access to elements on a specific position

    for (int i = 0; i < rows; ++i) {
    
    
        delete[] table[i];
    }
    delete[] table;
    table = nullptr;
}

Function pointer

#include <iostream>
#include <vector>

using namespace std;

int getNumber() {
    
    
    return 5;
}

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

bool ascendingCompare(int a, int b) {
    
    
    return a < b;
}

bool decendingCompare(int a, int b) {
    
    
    return a > b;
}


void sortAscending(vector<int> &numbersVector) {
    
    
    for (int i = 0; i < numbersVector.size(); ++i) {
    
    
        int bestIndex = i;
        for (int curIndex = i + 1; curIndex < numbersVector.size(); ++curIndex) {
    
    
            if (ascendingCompare(numbersVector[curIndex], numbersVector[bestIndex])) {
    
    
                bestIndex = curIndex;
            }
        }
        swap(numbersVector[i], numbersVector[bestIndex]);
    }
}


void sortDescending(vector<int> &numbersVector) {
    
    
    for (int i = 0; i < numbersVector.size(); ++i) {
    
    
        int bestIndex = i;
        for (int curIndex = i + 1; curIndex < numbersVector.size(); ++curIndex) {
    
    
            if (decendingCompare(numbersVector[curIndex], numbersVector[bestIndex])) {
    
    
                bestIndex = curIndex;
            }
        }
        swap(numbersVector[i], numbersVector[bestIndex]);
    }
}


// use function pointer to optimize two functions above
void customSort(vector<int> &numbersVector, bool (*compareFunc)(int, int)) {
    
    
    for (int i = 0; i < numbersVector.size(); ++i) {
    
    
        int bestIndex = i;
        for (int curIndex = i + 1; curIndex < numbersVector.size(); ++curIndex) {
    
    
            if (compareFunc(numbersVector[curIndex], numbersVector[bestIndex])) {
    
    
                bestIndex = curIndex;
            }
        }
        swap(numbersVector[i], numbersVector[bestIndex]);
    }
}


void printNumber(const vector<int> &numbersVector) {
    
    
    for (int i: numbersVector) {
    
    
        cout << i << " ";
    }
    cout << endl;
}

int main() {
    
    

    /*
     * introduction
     */
    int (*funcPtr)() = getNumber;
    cout << funcPtr() << endl;

    int (*funcAdd)(int, int) = add_two_num;
    cout << funcAdd(3, 3) << endl;

    // compile error when lacking parameter
    // Cannot initialize a variable of type 'int (*)()' with an lvalue of type 'int (int, int)': different number of parameters (0 vs 2)
    // int (*funcAdd)() = add_two_num;


    /*
     * demo of using function pointer
     */
    vector<int> myNumbers = {
    
    2, 5, 1, 3, 6, 4};
    sortAscending(myNumbers);
    printNumber(myNumbers);

    vector<int> myNumbers2 = {
    
    2, 5, 1, 3, 6, 4};
    customSort(myNumbers2, ascendingCompare);
    printNumber(myNumbers2);  // 1 2 3 4 5 6
    customSort(myNumbers2, decendingCompare);
    printNumber(myNumbers2);  // 6 5 4 3 2 1

    return 0;
}

Smart pointer

#include <iostream>
#include <memory>

using namespace std;

/*
 * smart pointer: the memory is deallocated automatically which means don't worry about leaking memory
 */

void test_demo() {
    
    
// create a unique pointer to an integer and assign value of 25 to address that unPtr1 is pointing to
    unique_ptr<int> unPtr1 = make_unique<int>(25);

//  cout << unPtr1 << endl;
    cout << *unPtr1 << endl;

//  unique_ptr<int> unPtr2 = unPtr1;  // error, can't assign a unique pointer to another unique pointer

    unique_ptr<int> unPtr2 = move(unPtr1);
    cout << *unPtr2 << endl;
//  cout << *unPtr1 << endl;  now, the pointer unPtr1 is empty, it's not pointer
}


class MyClass {
    
    
public:
    MyClass() {
    
    
        cout << "Constructor invoked" << endl;
    }

    ~MyClass() {
    
    
        cout << "Destructor invoked" << endl;
    }
};


void test_unique_pointer() {
    
    
    {
    
    
        unique_ptr<MyClass> unPtr1 = make_unique<MyClass>();  // Constructor invoked
    }  // Destructor invoked
}


void test_shared_pointer() {
    
    
    /*
     * the momory location will automatically be deallocated when there is no pointer pointing to that memory location
     */
    shared_ptr<MyClass> sharedPtr1 = make_shared<MyClass>();  // shared_ptr {...} [1 strong ref] [make_shared]
    cout << sharedPtr1.use_count() << endl;  // 1
    {
    
    
        shared_ptr<MyClass> sharedPtr2 = sharedPtr1;
        cout << sharedPtr1.use_count() << endl;  // 2
    }
    cout << sharedPtr1.use_count() << endl;  // 1
}

/*
 * main difference between a `weak pointer` and a `shared pointer`:
 * When assign a specific memory locaion to a `shared pointer`,
 *      that is going to increase the number of owners of that memory location,
 *      using shared pointer will keep object in memory alive.
 * But if assign that same memory location to a `weak pointer`,
 *      that will not increase the number of its owners,
 *      this means that we use weak pointer in order to observe objects in memory, to locate a specific object,
 *      but weak pointer will not keep that object alive if nothing else needs it.
 *
 */
void test_weak_pointer() {
    
    
    weak_ptr<int> weakPtr1;
    {
    
    
        shared_ptr<int> sharedPtr1 = make_shared<int>(25);  // shared_ptr 25 [1 strong ref] [make_shared]
        weakPtr1 = sharedPtr1;
        // value of weakPtr1 changes:
        // empty  ->  weak_ptr 25 [1 strong ref, 1 weak ref] [make_shared]  ->  expired [1 weak ref] [make_shared]
    }
}


int main() {
    
    
//    test_demo();
//    test_unique_pointer();
//    test_shared_pointer();
    test_weak_pointer();
    return 0;
}

Video Tutorial Link:https://www.youtube.com/watch?v=kiUGf_Z08RQ&t=1746s

猜你喜欢

转载自blog.csdn.net/qq_31362767/article/details/126032001