В чем реальная разница между указателями и ссылками? - PullRequest
29 голосов
/ 18 сентября 2008

АКА - Что за одержимость указателями?

Поскольку я действительно использовал только современные объектно-ориентированные языки, такие как ActionScript, Java и C #, я не совсем понимаю важность указателей и то, для чего вы их используете. Что мне здесь не хватает?

Ответы [ 22 ]

2 голосов
/ 18 сентября 2008

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

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

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

В Java вы все время используете указатели. Большинство переменных являются указателями на объекты - вот почему:

StringBuffer x = new StringBuffer("Hello");
StringBuffer y = x;
x.append(" boys");
System.out.println(y);

... печатает «Привет, ребята», а не «Привет».

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

2 голосов
/ 18 сентября 2008

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

2 голосов
/ 18 сентября 2008

Строки являются фундаментальными для C (и других родственных языков). При программировании на C вы должны управлять своей памятью. Вы не просто говорите «хорошо, мне понадобится куча строк»; вам нужно подумать о структуре данных. Сколько памяти вам нужно? Когда вы его выделите? Когда ты освободишь это? Допустим, вам нужно 10 строк, каждая из которых должна содержать не более 80 символов.

Хорошо, каждая строка представляет собой массив символов (81 символ - вы не должны забывать ноль, или вы пожалеете!), А затем каждая строка сама находится в массиве. Конечным результатом будет многомерный массив, похожий на

char dict[10][81];

Заметьте, кстати, что dict не является "строкой", "массивом" или "символом". Это указатель. Когда вы пытаетесь напечатать одну из этих строк, все, что вы делаете, это передаете адрес одного символа; C предполагает, что если он только начинает печатать символы, он в конечном итоге обнуляется И это предполагает, что если вы находитесь в начале одной строки, и вы прыгаете вперед на 81 байт, вы будете в начале следующей строки. И, фактически, получение вашего указателя и добавление к нему 81 байта - это единственный возможный способ *1009* для перехода к следующей строке.

Итак, почему указатели важны? Потому что без них ничего не поделаешь. Вы даже не можете сделать что-то простое, например, распечатать несколько строк; вы определенно не можете делать ничего интересного, например реализовывать связанные списки, или хэши, или очереди, или деревья, или файловую систему, или некоторый код управления памятью, или ядро, или ... что угодно. Вы ДОЛЖНЫ понимать их, потому что C просто вручает вам блок памяти, и мы сделаем все остальное, а для выполнения чего-либо с блоком необработанной памяти требуются указатели.

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

Теперь я свободно признаю, что программирование с указателями не требуется в 90% кода, написанного сегодня, и на самом деле, это прямо опасно в производственном коде. ХОРОШО. Все в порядке. А функциональное программирование практически не используется на практике. Согласен.

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

С здесь . Отличная статья.

1 голос
/ 18 сентября 2008

Долгое время я не понимал указатели, но понимал адресацию массива. Поэтому я обычно собираю некоторую область хранения для объектов в массиве, а затем использую индекс для этого массива в качестве понятия «указатель».

SomeObject store[100];
int a_ptr = 20;
SomeObject A = store[a_ptr];

Одна из проблем этого подхода заключается в том, что после того, как я изменил «A», мне пришлось бы переназначить его в массив «store», чтобы изменения были постоянными:

store[a_ptr] = A;

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

После того, как я научился понимать указатели, я отошел от реализации подхода к адресации массива. Аналогия все еще довольно верна. Просто учтите, что массивом «store» управляет среда выполнения языка программирования.

SomeObject A;
SomeObject* a_ptr = &A;
// Any changes to a_ptr's contents hereafter will affect
// the one-true-object that it addresses. No need to reassign.

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

  1. Чтобы избежать дорогостоящего объекта-копии операция ради производительность.
  2. Какой-то другой фактор не позволяет операция копирования объекта.
  3. Вы хотите, чтобы вызов функции имел побочные эффекты на объекте (не передать объект, передать указатель к ней).
  4. На некоторых языках - если вы хотите вернуть более одного значения из функция (хотя в целом избегать).
0 голосов
/ 15 мая 2009

Меня всегда огорчает сосредоточенность на таких вещах, как указатели или ссылки на языках высокого уровня. Действительно полезно думать на более высоком уровне абстракции с точки зрения поведения объектов (или даже просто функций), а не думать с точки зрения «позвольте мне посмотреть, если я отправлю туда адрес этой вещи, то эта вещь вернет мне указатель на что-то еще "

Рассмотрим даже простую функцию подкачки. Если у вас есть

void swap (int & a, int & b)

или

процедура Swap (var a, b: integer)

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

То же самое с объектами --- не думайте об идентификаторах объектов как указатели или ссылки на "материал". Вместо этого просто думайте о них, как о ОБЪЕКТАХ, на которые вы можете отправлять сообщения. Даже в примитивных языках, таких как C ++, вы можете пойти намного дальше, думая (и писать) на максимально высоком уровне.

0 голосов
/ 18 сентября 2008

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

0 голосов
/ 18 сентября 2008

Также просто кое-что стоит отметить, вы можете использовать указатели в C # (в отличие от обычных ссылок), помечая блок кода как небезопасный. Затем вы можете напрямую менять адреса памяти и выполнять арифметику с указателями и все такое. Он отлично подходит для очень быстрой манипуляции с изображениями (единственное место, где я лично его использовал).

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

0 голосов
/ 18 сентября 2008

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

0 голосов
/ 18 сентября 2008

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

Есть две вещи, которые сложны с указателями:

  1. Указатели на указатели, адресацию и т. Д. Могут стать очень загадочными. Это приводит к ошибкам, и их трудно прочитать.
  2. Память, на которую указывают указатели, часто выделяется из кучи, что означает, что вы несете ответственность за освобождение этой памяти. Чем больше становится ваше приложение, тем труднее выполнить это требование, и в результате возникают утечки памяти, которые трудно отследить.

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

0 голосов
/ 18 сентября 2008

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

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