Создание массивов в куче и обращение к ним с помощью указателей - PullRequest
1 голос
/ 22 июня 2009

У меня проблемы с пониманием следующего фрагмента кода, который я надеялся создать массив в куче и заполнить его символами от 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";

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

Как я понимаю выше, команда 'new' создает массив в куче и отправляет мне указатель на адрес, где находится массив. Поскольку указатель, который я назначаю (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";   

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

Спасибо

Ответы [ 6 ]

6 голосов
/ 22 июня 2009

Линия

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.

4 голосов
/ 22 июня 2009

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

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";
1 голос
/ 22 июня 2009

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

0 голосов
/ 22 июня 2009

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

0 голосов
/ 22 июня 2009

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

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

0 голосов
/ 22 июня 2009

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

...