I implemented a basic dynamic array using C++.
When deleting an element and shifting the others, the last element will be twice repeated (the original still exists after copying). I want to avoid memory leaking by deallocating the last element of the array. Currently, I do this by shrinking once after a number of deletions. Are there better solutions?
Finally, I am interested in some feedback on this implementation.
#include <iostream>
#include <stdexcept>
using namespace std;
class DynamicArray {
protected:
    int size;
    int* arr;
    int length;
    void grow() {
        copyToNewSize(size * 2);
    }
    void shrink() {
        copyToNewSize(size / 2);
    }
    void copyToNewSize(int newSize) {
        int* temp = new int[newSize];
        if (newSize > size)
            for (int i = 0; i < size; i++) {
                temp[i] = arr[i];
            }
        else
            for (int i = 0; i < newSize; i++) {
                temp[i] = arr[i];
            }
        delete[] arr;
        size = newSize;
        arr = temp;
    }
    void checkIndex(int index) {
        if (index >= length || index < 0)
            throw "Index is out of the array range!";
    }
public:
    DynamicArray(int startingSize) {
        size = startingSize;
        arr = new int[size];
        length = 0;
    }
    ~DynamicArray() {
        delete[] arr;
    }
    int push(int value) {
        length++;
        if (length == (size + 1))
            grow();
        arr[length - 1] = value;
        return length;
    }
    int pop() {
        length--;
        int value = arr[length];
        // memory leaking , delete arr[length]
        if (length <= size / 2)
            shrink();
        return value;
    }
    int insert(int index, int value) {
        checkIndex(index);
        length++;
        if (length == (size + 1))
            grow();
        for (int i = length - 1; i > index; i--) {
            arr[i] = arr[i - 1];
        }
        arr[index] = value;
        return length;
    }
    int remove(int index) {
        checkIndex(index);
        int value = arr[index];
        length--;
        for (int i = index; i < length; i++)
            arr[i] = arr[i + 1];
        // memory leaking , delete arr[length]
        if (length <= (size / 2))
            shrink();
        return value;
    }
    int get(int index) {
        checkIndex(index);
        return arr[index];
    }
    void set(int index, int value) {
        checkIndex(index);
        arr[index] = value;
    }
    int search(int value) {
        for (int i = 0; i < length; i++) {
            if (arr[i] == value)
                return i;
        }
        return -1;
    }
    int getLength() {
        return length;
    }
}
std::vector<int>or one of the other standard containers? \$\endgroup\$