Создание массивов в куче и обращение к ним с помощью указателей.

StackOverflow https://stackoverflow.com/questions/1026769

Вопрос

У меня возникли проблемы с пониманием следующего фрагмента кода, который, как я надеялся, создаст массив в куче и заполнит его символами от 9 до 0 (я знаю, что мог бы просто проиндексировать массив, как обычный массив стека, с обозначением [] чтобы сделать это, но я делаю это таким образом, чтобы попытаться глубже понять указатели):

int *ptrHeapArray = new int[10]; 

    for(int f=9; f>=0 ;f--)
    {
        *ptrHeapArray = f;
        ptrHeapArray++;
    }
    for(int f=0; f<10; f++)
        cout << ptrHeapArray[f]  << "\n";

Он выводит совершенно неожиданные значения.

Насколько я понимаю вышеизложенное, команда «новая» создает массив в куче и отправляет мне обратно указатель на адрес, где находится массив.Поскольку назначаемый мной указатель (ptrHeapArray) имеет размер int, я предположил, что могу использовать приращение поста указателя для навигации по массиву.Однако результаты показывают, что мои предположения ошибочны.

Это заставило меня задуматься, что, возможно, указатель, передаваемый ключевым словом «new», является просто указателем на весь массив и по какой-то причине не может использоваться для обхода массива.Поэтому я попытался создать еще один указатель на указатель, возвращаемый ключевым словом «new», и использовал его для заполнения моего массива:

int *ptrHeapArray = new int[10];  //array to hold FRANK data in 32 bit chunks
int *ptrToHeapArrayPointer = ptrHeapArray;

for(int f=9; f>=0 ;f--)
{
    *ptrToHeapArrayPointer = f;
    ptrToHeapArrayPointer++;
}
for(int f=0; f<10; f++)
    cout << ptrHeapArray[f]  << "\n";   

Это сработало нормально.Может ли кто-нибудь объяснить мне, почему я должен был это сделать и не мог просто использовать указатель, переданный мне по ключевому слову «новое»?

Спасибо

Это было полезно?

Решение

Линия

ptrHeapArray++;

в вашем первом цикле for увеличивается указатель, так что он больше не указывает на начало массива.

Линия

int *ptrHeapArray = new int[10];

выделяет память для 10 целых чисел и указывает ptrHeapArray на начало этой памяти.Затем в цикле for вы перемещаете этот указатель.Когда ptrHeapArray указывает на третье целое число:

[0] [1] [2] [3] [4]
 ^       ^       ^
orig.    |       |
         |       +-- ptrHeapArray[2]
         |
         +-- ptrHeapArray now points here

тогда ptrHeapArray[2] выдаст вам целое число в позиции, изначально пронумерованной цифрой 4.

Другие советы

Вы изменяете указатель в коде.После первого цикла в первом фрагменте указатель будет указывать на конец массива, а не на начало.Чтобы прояснить ситуацию, это тоже будет работать (не предлагается, но демонстрирует поведение):

int *ptrHeapArray = new int[10]; 

for(int f=9; f>=0 ;f--)
{
    *ptrHeapArray = f;
    ptrHeapArray++;
}

ptrHeapArray -= 10; // reset the pointer to its original location

for(int f=0; f<10; f++)
    cout << ptrHeapArray[f]  << "\n";

Ваш ptrToHeapArrayPointer назван неправильно, это просто стандартный int ptr, который вы указали в том же месте, что и ptrHeapArray.Если вы переименуете его в currentPositionPtr, ваш код станет для вас более понятным.

Когда вы выполняете ptrHeapArray++, он увеличивает ptrHeapArray.Когда вы начинаете распечатывать данные, ptrHeapArray больше не указывает на начало массива.

Проблема в том, что в вашем первом примере ptrHeapArray изначально установлен в начало массива.По мере прохождения цикла вы увеличиваете указатель, и к концу цикла for вы указываете на последний элемент массива.Когда вы выполняете цикл for для отображения всех ваших значений, вы индексируете значения за концом массива, поскольку ptrHeapArray указывает на последний элемент в выделенном вами массиве.

Также важно помнить, что вам, вероятно, следует позаботиться о том, чтобы не потерять исходный указатель, который вы получили в результате использования нового оператора, чтобы вы могли правильно освободить память, выделенную в куче.

В первом цикле вы увеличили свой указатель ptrHeapArray до конца массива.Итак, после выполнения первого цикла for ваш указатель указывает на конец массива, а не на начало.Следовательно, когда вы пытаетесь распечатать содержимое массива, вы получаете доступ к недопустимым выделениям памяти, и поведение будет неожиданным.Во втором случае вы делаете копию своего начального адреса перед присвоением значений массиву.Поэтому, когда вы попытаетесь распечатать содержимое с помощью копии, оно будет указывать на начало массива.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top