2009-06-22 5 views
1

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

Он печатает compleletly неожиданных значений.

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

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

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

Благодаря

ответ

6

Линия

ptrHeapArray++; 

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

Линия

int *ptrHeapArray = new int[10]; 

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

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

затем ptrHeapArray [2] даст вам целое число в позиции orignally нумеруется 4.

+0

Он в основном сжимает голову вашего массива –

+4

@Nathan: Не говорите так. Вы не различаете указатель и то, на что он указывает. Это различие новых программистов часто бывает трудно. «Глава массива» вообще не сбрасывается (перезаписывается). Это не изменилось. Просто нет указателя на него. – MSalters

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"; 
0

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

0

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

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

1

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

0

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