1

Could someone explain why pointers gets overwritten when variables are declared inside a loop?

For example, given the following snippet, and the user inputs 1 and 2. I would expect that the pNums array contain 2 pointers to 2 integers holding the value 1 and 2 respectively.

But instead, the console prints out 2 and 2;

#include <iostream>
using namespace std;

//Input "1 2"
int main() {
    int* pNums[2];
    for(int i = 0; i < 2; i++){
        int num;
        cin >> num;
        pNums[i] = (&num);
    }
    cout << (*pNums[0]) << endl;
    cout << (*pNums[1]) << endl; 
}

Why is this the case? And how do I get around it? What if, for example, we don't know how many numbers the user will put in, and instead of a for loop, we have a while loop? Until some conditions are met, we want to keep creating new pointers and store them into a pNums vector?

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
davidx1
  • 3,525
  • 9
  • 38
  • 65
  • 1
    The int variable is actually declared just the once for all for loop iterations and thus shares the same memory. You Want to look at dynamic variables and using new / delete. Or change to using another approach like a std::vector list where you can add numbers to the list. – Andrew Truckle Feb 10 '20 at 03:11
  • Why do you want to keep creating new *pointers*? Don't you want new *values*? What's the purpose of creating new pointers if there aren't any new things for them to point to? – David Schwartz Feb 10 '20 at 05:26

3 Answers3

3

There is only one num, and you are overwriting that. (And then causing Undefined Behavior, but never mind that.)

There are two simple ways to avoid this mistake.

1) Store objects, not pointers:

int nums[2];
for(int i = 0; i < 2; i++){
    cin >> nums[i];
}

2) Use dynamic allocation:

int* pNums[2];
for(int i = 0; i < 2; i++){
    int *p=new int;
    cin >> *p;
    pNums[i] = p;
}
Beta
  • 96,650
  • 16
  • 149
  • 150
  • But remember to delete the data you declared to avoid memory leaks. Or use smart pointers. – Andrew Truckle Feb 10 '20 at 03:30
  • @AndrewTruckle If we use dynamic allocation, when/how do I delete the data? And what are smart pointers? Could you please point me to a tutorial or documentation if it's too long to explain here? – davidx1 Feb 10 '20 at 03:33
  • @Synia See https://www.geeksforgeeks.org/new-and-delete-operators-in-cpp-for-dynamic-memory/ and https://learn.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=vs-2019. A good tutorial will explain these approaches. – Andrew Truckle Feb 10 '20 at 05:03
0
for(int i = 0; i < 2; i++){
    int num; //< this is num. It lives here.
    cin >> num; 
    pNums[i] = (&num);  //< you have taken the address of num (twice!)
}
// here is when 'num' is destroyed (no longer in scope)

// so this is now pointing at something that doesn't exist. 
cout << (*pNums[0]) << endl;
Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
robthebloke
  • 9,331
  • 9
  • 12
0

The pointers that you are storing in pNums are to two instances of the variable num in the for block. There is one instance of the variable in each for loop iteration and these variables live only until the end of their respective iteration of the for loop body is reached.

Therefore your pointers will be invalid when the for loop exits and so trying to dereference them with e.g. *pNums[0] causes undefined behavior.

Don't store pointer, store values:

#include <iostream>
using namespace std;

//Input "1 2"
int main() {
    int pNums[2];
    for(int i = 0; i < 2; i++){
        int num;
        cin >> num;
        pNums[i] = num;
    }
    cout << pNums[0] << endl;
    cout << pNums[1] << endl; 
}

and if you need a variable number of entries in the array, use std::vector.

walnut
  • 21,629
  • 4
  • 23
  • 59