Каковы варианты использования и преимущества указателей? [закрыто]

10

Я часто изо всех сил пытаюсь увидеть преимущества указателей (за исключением программирования низкого уровня).

Зачем использовать char * вместо String или char [] или какие преимущества дает арифметика с указателями.

Так каковы плюсы и случаи использования указателей?

Olivers
источник
6
Это звучит немного элитарно, но, имхо, если вам нужно спросить о плюсах и минусах указателей, вам, скорее всего, они не нужны.
Jas
3
Вероятно! Но вопрос все еще актуален!
Zolomon
1
Это также не очень зависит от языка, так как не все такие языки программирования имеют реальные указатели в смысле Си.
Дэвид Торнли

Ответы:

6

Указатели необходимы для динамического расположения в памяти, многих структур данных и эффективной обработки больших объемов данных. Без указателей вам пришлось бы распределять все программные данные глобально или в функциях или аналогичных средствах, и вы бы не обратились за помощью, если бы объем данных превысил то, что вы изначально допустили. Я не решаюсь использовать абсолюты здесь, но, насколько я знаю, все современные компьютерные языки имеют указатели в той или иной форме.

В большинстве языков, в которых используются указатели, существуют определенные виды ссылок, которые являются указателями, и, возможно, некоторые виды ссылок, которые не являются таковыми, и дальнейшая нотационная разница отсутствует. consЯчейка Lisp - это пара указателей, хотя a fixnumне является указателем. В Java переменная, используемая для экземпляра класса, является указателем, но не intявляется. Синтаксис языка не отражает этого.

C необычен тем, что указатели являются необязательными, явными и допускают явную арифметику указателей. Вполне возможно писать struct foo bar; struct foo * baz;, и как только вы выделите память, bazвы можете использовать оба barи bazдля представления struct foos. Поскольку указатели являются необязательными, полезно иметь нотационные различия. (Это важно в C ++ для умных указателей, как дано boost::shared_ptr<foo> bar;, bar.reset()имеет одно значение и bar->reset(), вероятно, будет иметь другое значение.)

(На самом деле, явные указатели часто использовались в других языках, когда C первоначально разрабатывался, например, ^в Pascal. C - более старый язык, чем обычно используется сегодня, и это видно.)

Одной из целей разработки C было написать Unix, и, следовательно, необходимо было детально обрабатывать области памяти. (C на самом деле является одним из семейства языков реализации системы, распространенных при разработке, другой пример - Cybol для компьютеров с управляющими данными. C - тот, который стал большим хитом.) Следовательно, можно напрямую манипулировать указателями C, назначение адресов памяти и вычисление новых. Это также привело к некоторым проектным решениям в C. Массивы C в значительной степени основаны на арифметике указателей, и, действительно, массив превращается в указатель в очень многих ситуациях. Передача переменных в функции C по ссылке осуществляется указателем. Не было особой необходимости в массивах и передаче переменных по ссылке в форме, которую имели другие современные языки, поэтому Си не получил их.

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

Дэвид Торнли
источник
очень хороший ответ
Кейт Грегори
1
Я принимаю этот ответ, потому что он лучше всего описывает разницу, которую я не мог понять между указателями в C / C ++ и Reference в Java.
OliverS
Было бы хорошо добавить краткое объяснение того, почему Java не использует указатели, чтобы лучше прояснить воспринимаемый «обман» Гослинга (основного создателя Java).
Гвидо Ансельми
10

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

Здесь нет «плюсов» и «минусов» указателей. Они просто инструмент, как молоток.

zvrba
источник
5
В Java нет указателей. Тем не менее, можно построить связанный список и двоичное дерево. Существует различие между ссылками (как в Java) и указателями (как в C).
StartClass0830
7
Нет разницы между ссылками и указателями. Арифметика указателей зависит от C; Есть другие языки, которые имеют указатели, но не имеют арифметику указателей (например, Pascal).
zvrba
1
Указатели и ссылки не являются синонимами, как вы думаете. Прочитайте это, чтобы увидеть различия. stackoverflow.com/questions/57483/…
StartClass0830
4
Чтобы обратиться к первым двум пунктам этого списка: ссылки Java могут быть переназначены, и они могут указывать на ноль. Отличительная особенность указателя заключается в том, что вы можете косвенно ссылаться на другой объект. Мой лакмусовый тест: если вы можете построить круговую структуру данных (которую вы можете с помощью ссылок Java), это указатель. (Обратите внимание, что вы не можете построить круговую структуру данных со ссылками на C ++.)
zvrba
1
Существует разница между указателями и ссылками. C #, например, имеет оба . ( blogs.msdn.com/b/ericlippert/archive/2009/02/17/… )
Стивен Эверс
2
  • С помощью указателей вы можете выделять и освобождать память во время выполнения.
  • И вы можете использовать большие структуры данных вне допустимой области без копирования.

Ссылки на C ++, Java и другие языки того же типа - это просто «безопасные указатели». И эти ссылки часто используются в Java.

Gulshan
источник
1
Ссылки в C ++ НЕ являются безопасными указателями. Ссылки на C ++ не имеют ничего общего с указателями. Ссылки на C ++ являются псевдонимами . Они не могут быть назначены NULLи не могут быть изменены после их создания.
Билли ONEAL
@Billy: ссылки на C ++ обычно реализуются с использованием указателей, и в некоторых случаях они работают аналогично, поэтому люди продолжают думать о них как о некоем ограниченном указателе.
Дэвид Торнли
2

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


источник
2

char*это грязный пример указателей. Вам, вероятно, лучше использовать std::string(или какой-то лучший тип, который обрабатывает вашу специальность Unicode / ANSI / Multibyte), чем char*. Почти для любого другого примера указателей ( Employee*, PurchaseOrder*, ...), однако, есть много преимуществ:

  • область действия больше, чем одна функция - выделите объект в куче и долгое время передайте указатель
  • более быстрые вызовы функций для больших объектов, поскольку у вас нет стоимости копирования по значению
  • один из способов включить функцию для изменения переданных ей параметров
  • сэкономить место и время в коллекциях, копируя только адрес, а не весь объект

Фактически, указатели настолько важны, что большинство языков, у которых их нет, на самом деле имеют только их. Ссылочные типы в C # и Java по сути являются указателями, замаскированными как сплошные объекты.

Теперь манипулирование указателем ( p++на указателе или p += delta) - это целая другая история. Некоторые люди думают, что это опасно, некоторые люди думают, что это здорово. Но это еще дальше от вашего вопроса.

Кейт Грегори
источник
1

Указатели могут быть более быстрыми и могут вызывать меньше накладных расходов, как в структурах данных, так и в плане сокращения объема выполнения программы. (Обратите внимание на слово «можно».)

В общем случае правило заключается в том, что если вы выделили ресурс, выполнив собственное выделение или сделав что-то, сделав это от вашего имени, то ваша задача - освободить его, когда закончите.

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

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

Часто то, что делает указатели «сложными», просто не понимает, что происходит на аппаратном уровне. Это не что иное, как косвенность.

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

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

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

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

Уолт Стоунбернер
источник
0

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

Ларри Коулман
источник
-1

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

Пол Натан
источник