Указатель C ++ перезаписывается для циклов - PullRequest
1 голос
/ 10 февраля 2020

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

Например, с учетом следующего фрагмента и ввода пользователем 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 l oop у нас будет while l oop? Пока не будут выполнены некоторые условия, мы хотим продолжать создавать новые указатели и сохранять их в pNums векторе?

Ответы [ 3 ]

3 голосов
/ 10 февраля 2020

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

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

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

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

2) Использовать динамическое выделение c:

int* pNums[2];
for(int i = 0; i < 2; i++){
    int *p=new int;
    cin >> *p;
    pNums[i] = p;
}
0 голосов
/ 10 февраля 2020

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

Поэтому ваш указатели будут недействительными при выходе из for l oop, поэтому попытка разыменовать их, например, *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 голосов
/ 10 февраля 2020
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;
...