Какой смысл указателей? - PullRequest
12 голосов
/ 12 мая 2009

Какой смысл указателей в C ++, когда я могу просто объявить переменные? Когда их целесообразно использовать?

Ответы [ 12 ]

29 голосов
/ 12 мая 2009

Указатели лучше всего понятны из различий C & C ++ в передаче переменных в функции.

Да, вы можете передать либо целую переменную, либо просто указатель на нее (жаргон - по значению или по ссылке, соответственно).

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

Лучше просто "указать" на это. Вы говорите: «Вот указатель на большой кусочек памяти». И эта маленькая косвенность экономит массу времени.

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

16 голосов
/ 12 мая 2009

Указатели наиболее полезны при работе со структурами данных, размер и форма которых неизвестны во время компиляции (списки, деревья, графики, массивы, строки ...).

Редактировать

Эти похожие ответы также могут помочь (верхний ответ во второй ссылке определенно стоит посмотреть):

В C ++ я не могу понять указатели и классы

Каковы барьеры на пути понимания указателей и что можно сделать для их преодоления?

2 голосов
/ 12 мая 2009

Указатели также отлично подходят для передачи изменяемого аргумента в функцию, чтобы вызывающий мог «увидеть изменение». Вы можете спросить: «Но почему бы не использовать ссылку?». Мне нравится аргумент Google:

http://google -styleguide.googlecode.com / SVN / багажник / cppguide.xml # Reference_Arguments

1 голос
/ 12 мая 2009

На самом базовом уровне указатели позволяют вам связывать непересекающиеся блоки памяти. Простой (надуманный, по общему признанию) пример, в котором вам могут помочь указатели, - это алгоритм, для которого требуется массив из 1000000000000 целых чисел. Такой массив был бы слишком большим, чтобы поместиться в ОЗУ компьютера, на котором я сейчас печатаю, если бы я попробовал такое определение, как:

int bigMatrix[1000000000000]; // I can't allocate this much contiguous memory

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

int *bigMatrix[1000000]; // Each pointer refers to a sub-array 
                         // of 1000000 elements on disk

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

1 голос
/ 12 мая 2009

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

Указатели часто используются в ситуациях программирования. Например, когда вы ссылаетесь на массив по имени, например, array[i] = 3; Компилятор делает некоторую причудливую математику, которая в итоге превращает этот код в

(адрес массива) + (sizeof (элементы массива) * i) = 3;

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

0 голосов
/ 19 апреля 2012

Указатели хранят адрес памяти, поэтому вы можете использовать их всякий раз, когда вам нужен адрес памяти чего-либо. Это может быть полезно для таких вещей, как управление памятью, зная, где хранятся ваши данные. Мой профессор сказал нам, что это прекрасная вещь для продвинутых программ с точки зрения обеспечения того, что ваши данные непрерывно расположены в памяти (как строки в стиле c).

Надеюсь, это какая-то форма помощи для вас!

-Zen, новичок в c ++

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

Мне кажется, что вы еще не узнали о динамическом распределении памяти. Есть два способа выделить память в C ++: статически и динамически. Вы уже знакомы со статическим размещением (т.е. объявлением переменных). Это замечательно, если во время написания вашей программы вы точно знаете, сколько переменных (точнее, памяти) вам нужно.

Но что, если вы этого не сделаете? Например, предположим, что вы читаете, что содержит набор чисел, которые необходимо отслеживать. Зачем? Я не знаю, но это не главное.

Ну, вы можете начать с массива:

int array[100];

Но что, если в файле более 100 чисел? В конце концов вам понадобится более гибкое решение:

int *array = new int[size];
// do stuff
delete [] array;

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

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

Предположим, вы пишете текстовый редактор. В этом случае вы заранее не знаете размер документа. У вас может возникнуть соблазн объявить что-то вроде

  char Document[10000];

но, конечно, однажды кто-то захочет использовать ваш редактор в гораздо большем документе. Так что эта попытка бесполезна; и вам нужен способ запросить новую память в время выполнения (вместо времени компиляции).

В C ++ для этого используется оператор new, который возвращает указатель на только что выделенную память:

  char* pDocument = new char[getSizeOfDocument()];

(Обратите внимание, что этот пример слишком упрощен. В реальной жизни вы бы, конечно, не сделали это так, а вместо этого использовали бы что-то вроде std :: string и std :: vector, которые внутренне делают это распределение.)

0 голосов
/ 12 мая 2009

С архитектурной точки зрения указатели являются экономичным способом моделирования отношения 0 .. n:

struct A {
  vector<const B *> *pBees;
  A() : pBees(nullptr) {}
  void notice_bee(const B *pB) { 
    if (!pBees)
      pBees = new vector<const B *>;
    pBees.push_back(pB)
  }
  ~A() { 
    delete pBees; // no need to test, delete nullptr is safe
  }
  size_t bees_noticed() { return pBees ? pBees->size : 0 }
};

Если подавляющему большинству объектов A никогда не потребуется обращать внимание на какие-либо объекты B, нет никаких причин, по которым каждый объект A должен иметь вектор нулевой длины. Под Gnu C ++ 4.0.1 sizeof (вектор) равен 12; sizeof (вектор *) равен 4.

0 голосов
/ 12 мая 2009

Помимо эффективности и гибкости. Основной смысл указателей в C / C ++ заключается в том, что аппаратное обеспечение работает так, что вы не сможете увидеть драйвер устройства, диспетчер памяти или эффективный кэш, не используя указатели где-то вдоль линии.

Одной из основных целей разработки для первого компилятора C было стать «переносимым языком ассемблера» и иметь возможность делать на языке более высокого уровня все, что вы могли бы сделать с помощью традиционной сборки / машинного кода. Это означает возможность манипулировать адресами напрямую, что является точкой указателей.

Однако, следуя принципу KISS, не используйте указатели, если они действительно не упрощают задачу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...