c++scopedynamic-arrays

C++: dynamic array unexpectedly working and on the scope of variables


I'm super duper new to coding and I'm just learning this as a hobby. I'm following a course and this is the code I wrote (user input to a dynamically created array):

#include <iostream>

using namespace std;

int main()
{
    int capacity = 5;
    int* numbers = new int[capacity];
    int index=0;

    while (true)
    {       
        cout << "Please enter a whole number. ";
        cin >> numbers[index];
        if (cin.fail())
        {
            cout << "That's not a whole number, ya dingus. Here's all yer numbers so far:" << endl;
            break;
        }
        index++;
        if (index == capacity)
        {
            int* morenumbers = new int[2*capacity];
            for (int j = 0; j < index;j++)
            {
                morenumbers[j] = numbers[j];
            }
            delete[] numbers;
            numbers = morenumbers;
        }
    }

    for (int i = 0; i < index;i++)
        cout << numbers[i] << endl;
    delete[] numbers;

    return 0;
}

My questions are:

  1. I set the initial size of the array to 5 and it can be increased to 10. Why the heck does it work for 20 numbers as well?

  2. The variable index that I declared changes in the while loop. So, if I'm not wrong, its scope is within the while loop, right? Then, why is it that I can use it outside of the while loop (as for example my last for loop that prints out all the entered numbers)?

My main focus right now is not writing efficient code, but learning what the commands do, so despite the code apparently working flawlessly, I want to know why it works.


Solution

  • I set the initial size of the array to 5 and it can be increased to 10. Why the heck does it work for 20 numbers as well?

    It doesn't "work", actually. You have a logic bug in your code, which causes Undefined Behavior after 10 numbers have been entered.

    When you re-allocate the array, you are not updating the capacity variable to reflect the new size. So, you will end up re-allocating the array only 1 time total, after the 5th number is entered. After the 10th number is entered, you will start trashing memory when you save subsequent numbers into array slots that you did not allocate memory for.

    You need to update the capacity variable when you update the numbers variable, eg:

    numbers = morenumbers;
    capacity *= 2; // <-- add this!
    

    That being said, if you want to learn C++ properly, then modern practice is to NOT directly use new[]/delete[] at all. Consider them only for advanced use cases, not for beginner use cases. In this example, you can instead use std::vector, which is C++'s standard dynamic array type. Let it handle the memory management for you, eg:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
        vector<int> numbers(5);
        int number, index = 0;
    
        while (true)
        {       
            cout << "Please enter a whole number. ";
    
            if (!(cin >> number))
            {
                cout << "That's not a whole number, ya dingus." << endl;
                break;
            }
    
            if (index == numbers.size())
                numbers.resize(2*index);
    
            numbers[index] = number;
            ++index;
        }
    
        cout << "Here's all yer numbers so far:" << endl;
    
        for (int i = 0; i < index; ++i)
            cout << numbers[i] << endl;
    
        return 0;
    }
    

    Which can be simplified by getting rid of index altogether:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
        vector<int> numbers;
    
        while (true)
        {       
            cout << "Please enter a whole number. ";
    
            int number;
            if (!(cin >> number))
            {
                cout << "That's not a whole number, ya dingus." << endl;
                break;
            }
    
            numbers.push_back(number);
        }
    
        cout << "Here's all yer numbers so far:" << endl;
    
        for (int number : numbers)
            cout << number << endl;
    
        return 0;
    }
    

    The variable index that I declared changes in the while loop. So, if I'm not wrong, its scope is within the while loop, right?

    You declared index in the outermost {} block of main(), so its lifetime ends at the end of main(), and its scope includes both loops but is not limited to either loop.

    Then, why is it that I can use it outside of the while loop (as for example my last for loop that prints out all the entered numbers)?

    Because index is still in scope when the for loop is reached. See Scope on cppreference.com for more details.