2013-10-02 2 views
0

Я пытаюсь изучить C++ самостоятельно, используя Jesse Liberty, «Обучайте себя C++ за 24 часа». Я написал эту короткую программу для определения указателей на C++.Попытка понять указатели в C++

#include <iostream> 

void hMany(int count); // hMany function prototype 


void hMany(int count){ 

    do { 
     std::cout << "Hello...\n"; 
     count--; 

     } while (count >0); 

}; 


int main (int argc, const char * argv[]) { 


    int counter; 
    int * pCounter = &counter; 

    std::cout << "How many hellos? "; 
    std::cin >> counter; 

    hMany(*pCounter); 

    std::cout << "counter is: " << counter << std::endl; 
    std::cout << "*pCounter is: " << *pCounter << std::endl; 

    return 0; 
} 

Полученный результат:

How many hellos? 2 
Hello... 
Hello... 
counter is: 2 
*pCounter is: 2 

Какая польза от прохождения указатели (*) pCounter против аргумента (счетчик)?

Любая помощь была бы принята с благодарностью. Луис

Update:

Ok. Программа работает, и теперь я полностью понимаю указатели на C++. Спасибо всем за ваши ответы. Пробовав код Чолетта, я получил 2 предупреждения (а не ошибки). Один был! Нет предыдущего прототипа функции hMany и * pCount--! Результат выражения не используется. Я смог исправить прототип самостоятельно, но я не мог понять предупреждение * pCount.

Я попросил моего друга Тони получить помощь, и вот его ответ.

Скобки делают вещи в правильном порядке.

(*pCount)-- 

говорит следовать указатель на целое число он указывает, а затем уменьшаем число, которое является то, что вы хотите сделать.

*pCount-- 

заканчивает тем, что делает не то, что компилятор воспринимает его как

*(pCount—) 

, который говорит уменьшает указатель первым, оставив его, указывая на «целое», прежде чем тот, который вы хотите изменить (нет такой вещи, поскольку у вас есть только одно целое, с которым вы вызывали эту функцию), затем следуйте этому декрементированному указателю и ничего не делайте с целым числом в этой ячейке памяти. Вот почему компилятор жаловался, что результат выражения не использовался. Компилятор был прав. Этот код неправильно уменьшает указатель, извлекает неправильное целое число и не сохраняет это неправильное целое в любом месте.

Вот правильный код для тех, кто не знаком с C++, который может быть заинтересован.

включает

недействительного hMany (INT * pCount); // Функция hMany прототип

недействительными hMany (интермедиат * pCount) {// * pCount получает адрес графа

do { 
    std::cout << "Hello...\n"; 


    // The parentheses make things happen in the correct order. 
    // says to follow the pointer to the integer it points to, 
    // and then decrement the integer. 

      (*pCount)--; 

} while (*pCount >0); 

}

INT основных (INT ARGC, Const символ * ARGV []) {

int counter; 
int * pCounter = &counter; 

std::cout << "How many hellos? "; 
std::cin >> counter; 

hMany(pCounter); // passing the address of counter 

std::cout << "counter is: " << counter << std::endl; 
std::cout << "*pCounter is: " << *pCounter << std::endl; 

return 0; 

}

+1

_Pointers_ not _Points_. – deepmax

+10

Пожалуйста, получите [* good * book] (http://stackoverflow.com/q/388242/1171191). 'C++' не является языком для изучения "за 24 часа". Вы просто изучите ужасные практики, которые трудно будет отучить и дадут вам плохое впечатление о языке. – BoBTFish

+0

Я думаю, что ответы ниже отсутствуют. В коде выше никакие указатели не передаются функции. – john

ответ

0

В чем преимущество передачи точки (* pCounter) против аргумента (счетчик)?

Там нет «выгода», это то, как вы должны передать значение, на который указывает указатель pCounter.

hMany(*pCounter) -> разыменовывает pCounter получить значение

2
int counter; 
int * pCounter = &counter; 

... 

hMany(*pCounter); // Pass by value 

hMany(counter); // Pass by value 

Какая польза от прохождения точки (* pCounter) против аргумента (счетчик)?

В этом случае ничего, это всего лишь образовательный пример. Он показывает, что вы можете разыменовать указатель и получить его значение на *.

Кроме того, оба случая проходят по значению.

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

0

Разница - это область действия переменной.

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

вы можете думать об этом так:

стек:

текущий стек функции:

[ ] 
[ ] 
[ ] 
[ ] 

при вызове другой 1 элемент добавляется

[ ] 
[ ] 
[ ] 
[ ] 
[newel] 

при выходе из функции она не будет удалена, так его, как это снова

[ ] 
[ ] 
[ ] 
[ ] 

newelement значение не могу доверять не больше.

Но если это копия указателя, вы изменить не значение указателя копирования , но значение этого места он указывает тоже так стек будет как этот

[ ] 
[ actual_value] 
[ ] 
[ pointer_to_value] 

, чем вызов функции

[ ] 
[ actual_value] 
[ ] 
[ pointer_to_value] 
[ pointer_to_value_copy] 

который изменит actual_value в стеке и бросить удаляемый копию pointer_to_value

[ ] 
[ actual_value**changed] 
[ ] 
[ pointer_to_value] 
2

Нет никакой разницы между использованием *pCounter и counter. В обоих случаях вы передаете значение переменной counter.Однако, если вы действительно передаете указатель, вы получите другое поведение.

Рассмотрим несколько иную программу:

#include <iostream> 

void hMany(int* pCount); // hMany function prototype 


void hMany(int* pCount){ 

    do { 
     std::cout << "Hello...\n"; 
     --*pCount; 

     } while (*pCount >0); 

} 


int main (int argc, const char * argv[]) { 


    int counter; 
    int * pCounter = &counter; 

    std::cout << "How many hellos? "; 
    std::cin >> counter; 

    hMany(pCounter); 

    std::cout << "counter is: " << counter << std::endl; 
    std::cout << "*pCounter is: " << *pCounter << std::endl; 

    return 0; 
} 

В этом случае, ваш выход будет:

How many hellos? 2 
Hello... 
Hello... 
counter is: 0 
*pCounter is: 0 

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

+1

Обратите внимание, что почти всегда были бы предпочтительными ссылки для этой цели. – cHao

+0

Спасибо за помощь, предоставленную всем. Это облегчило мою путаницу с указателями. Значение передавалось, а не адрес. Теперь я понимаю * whatEver получает значение, а whatEver - адрес, в котором хранится значение. Тем не менее, я скопировал ваш код и вставил его на Xcode 4.2, но у меня не было такого же результата, как у вас. У меня была ошибка на void hMany (int * pCount)! Нет предыдущего прототипа функции hMany. Я изменил его на void hMany (int * pCount); и ошибка исчезла. У меня все еще есть и ошибка на * pCount--; ! выражение результат не использовался. Есть идеи? – robles1999

+0

Ах, извинения, я забыл обновить прототип. Я отредактирую ответ. Что касается другой жалобы компилятора, это звучит как предупреждение, а не ошибка. '* pCount -' возвращает предыдущее значение, а также декремент, и компилятор указывает, что вы его не использовали. Неужели он отказывается компилировать? (В любом случае, '- * pCounter', вероятно, лучше, поэтому я тоже изменил код.) – Chowlett

0

Указатель фактически содержит адрес памяти с информацией о типе значения, которое представляет собой адрес памяти. Он может использоваться для передачи объекта в адрес памяти, не создавая его снова, чтобы изменить его значение или что-то в этом роде.

Но в вашей программе я не вижу никакой пользы от использования указателя, потому что функция C++, hMany в вашем случае, внутренне повторно создает экземпляр типа значения в своем аргументе, `int count 'в вашем случае.

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

Смежные вопросы