Может ли кто-нибудь объяснить, почему указатели перезаписываются при объявлении переменных внутри цикла?

Например, с учетом следующего фрагмента и пользовательского ввода 1 и 2. Я ожидаю, что массив pNums содержит 2 указателя на 2 целых числа, содержащих значения 1 и 2 соответственно.

Но вместо этого консоль печатает 2 и 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; 
}

Почему это так? И как мне обойти это? Что если, например, мы не знаем, сколько чисел введет пользователь, и вместо цикла for мы получим цикл while? Пока не будут выполнены некоторые условия, мы хотим продолжать создавать новые указатели и сохранять их в векторе pNums?

1
davidx1 10 Фев 2020 в 06:02

3 ответа

Лучший ответ

Существует только один num, и вы перезаписываете это. (и затем вызываете неопределенное поведение, но не обращайте на это внимания.)

Есть два простых способа избежать этой ошибки.

1) Храните объекты, а не указатели:

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

2) Используйте динамическое размещение:

int* pNums[2];
for(int i = 0; i < 2; i++){
    int *p=new int;
    cin >> *p;
    pNums[i] = p;
}
3
Beta 10 Фев 2020 в 03:15
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;
0
Andrew Truckle 10 Фев 2020 в 05:18

Указатели, которые вы храните в pNums, относятся к двум экземплярам переменной num в блоке for. В каждой итерации цикла for существует один экземпляр переменной, и эти переменные живут только до тех пор, пока не будет достигнут конец их соответствующей итерации тела цикла for.

Следовательно, ваши указатели будут недействительными, когда завершается цикл for, и поэтому он пытается разыменовать их, например, с помощью. *pNums[0] вызывает неопределенное поведение .

Не хранить указатель, хранить значения:

#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; 
}

И если вам нужно переменное количество записей в массиве, используйте std::vector.

0
walnut 10 Фев 2020 в 03:11