Похоже, что мышление об использовании указателей в языках программирования постепенно изменилось, поэтому стало общепринятым, что указатели считаются рискованными (если не явным «злом» или подобным повышением).
Каковы были исторические события для этого изменения мышления? Были ли какие-то конкретные, оригинальные события, исследования или другие события?
Например, поверхностный взгляд на переход с C на C ++ на Java, кажется, показывает тенденцию дополнять, а затем полностью заменять указатели ссылками. Однако настоящая цепочка событий была, вероятно, гораздо более тонкой и сложной, чем эта, и не настолько последовательной. Функции, которые сделали это в этих основных языках, могли появиться в другом месте, возможно, задолго до этого.
Примечание: я не спрашиваю о реальных достоинствах указателей по сравнению с ссылками и чем-то еще. Я сосредоточен на обоснованиях этого очевидного сдвига.
Ответы:
Обоснованием была разработка альтернатив указателям.
Под капотом любой указатель / ссылка / и т. Д. Реализуется как целое число, содержащее адрес памяти (или указатель). Когда вышел C , эта функциональность была представлена как указатели. Это означало, что все, что может сделать базовое оборудование для адресации памяти, может быть сделано с помощью указателей.
Это всегда было «опасно», но опасность относительна. Когда вы создаете программу из 1000 строк или когда у вас есть процедуры обеспечения качества программного обеспечения IBM, эта опасность может быть легко устранена. Однако не все программное обеспечение разрабатывалось таким образом. Таким образом, возникла потребность в более простых структурах.
Если вы думаете об этом, a
int&
и aint* const
действительно имеют один и тот же уровень безопасности, но один из них имеет более приятный синтаксис, чем другой.int&
также может быть более эффективным, поскольку он может ссылаться на int, хранящийся в регистре (анахронизм: это было верно в прошлом, но современные компиляторы настолько хороши в оптимизации, что вы можете иметь указатель на целое число в регистре, пока Вы никогда не используете какие-либо функции, которые требуют фактического адреса, например++
)Когда мы переходим на Java , мы переходим на языки, которые предоставляют некоторые гарантии безопасности. C и C ++ не предоставили ни одного. Java гарантирует, что выполняются только легальные операции. Чтобы сделать это, Java полностью покончил с указателями. Они обнаружили, что подавляющее большинство операций указателя / ссылки, выполняемых в реальном коде, были вещами, для которых ссылок было более чем достаточно. Только в нескольких случаях (таких как быстрая итерация по массиву) действительно нужны указатели. В этих случаях java получает удар во время выполнения, чтобы избежать их использования.
Этот шаг не был монотонным. C # повторно введенные указатели, хотя и в очень ограниченной форме. Они помечены как « небезопасные », что означает, что они не могут быть использованы ненадежным кодом. У них также есть явные правила относительно того, на что они могут и не могут указывать (например, просто недопустимо увеличивать указатель после конца массива). Тем не менее, они обнаружили, что было несколько случаев, когда требовалась высокая производительность указателей, поэтому они вернули их обратно.
Также представляют интерес функциональные языки, которые вообще не имеют такого понятия, но это совсем другое обсуждение.
источник
Некоторая косвенность необходима для сложных программ (например, рекурсивные или структуры данных переменного размера). Однако нет необходимости реализовывать это косвенное обращение с помощью указателей.
Большинство языков программирования высокого уровня (т.е. не ассемблер) достаточно безопасны для памяти и не допускают неограниченного доступа к указателю. Семья C здесь самая странная.
C развился из B, который был очень тонкой абстракцией по сравнению с необработанной сборкой. У Б был один тип: слово. Слово может быть использовано как целое число или как указатель. Эти два эквивалентны, когда вся память рассматривается как один непрерывный массив. C сохранил этот довольно гибкий подход и продолжал поддерживать небезопасную арифметику указателей. Вся система типов C - это скорее запоздалая мысль. Эта гибкость доступа к памяти сделала C очень подходящим для его основной цели: создание прототипа операционной системы Unix. Конечно, Unix и C оказались довольно популярными, так что C также используется в приложениях, где этот низкоуровневый подход к памяти на самом деле не нужен.
Если мы посмотрим на языки программирования, которые были до C (например, диалекты Fortran, Algol, включая Pascal, Cobol, Lisp, ...), то некоторые из них поддерживают указатели, подобные C. Примечательно, что концепция нулевого указателя была изобретена для Algol W в 1965 году. Но ни один из этих языков не пытался быть C-подобным, эффективным языком систем с низкой абстракцией: Fortran предназначался для научных вычислений, Algol разработал несколько довольно продвинутых концепций, Lisp был больше исследовательский проект, чем язык промышленного уровня, и Cobol был сосредоточен на бизнес-приложениях.
Сбор мусора существовал с конца 50-х годов, то есть задолго до C (начала 70-х). Для правильной работы GC требуется безопасность памяти. Языки до и после C использовали GC как обычную функцию. Конечно, это делает язык намного сложнее и, возможно, медленнее, что было особенно заметно во времена мэйнфреймов. Языки GC, как правило, ориентированы на исследования (например, Lisp, Simula, ML) и / или требуют мощных рабочих станций (например, Smalltalk).
С меньшими, более мощными компьютерами вычисления в целом и языки GC, в частности, стали более популярными. Для приложений не в реальном времени (а иногда даже тогда) GC сейчас является предпочтительным подходом. Но алгоритмы GC также были предметом интенсивных исследований. В качестве альтернативы улучшена безопасность памяти без GC, особенно в последние три десятилетия: заметными нововведениями являются RAII и интеллектуальные указатели в C ++ и средство проверки системы / заимствования Rust.
Java не вводила новшеств, будучи безопасным для памяти языком программирования: она в основном брала семантику GCed, безопасного языка памяти Smalltalk, и сочетала их с синтаксисом и статической типизацией C ++. Затем он продавался как лучший, более простой C / C ++. Но это только внешне потомок C ++. Отсутствие указателей в Java во многом связано с объектной моделью Smalltalk, а не с отказом от модели данных C ++.
Таким образом, «современные» языки, такие как Java, Ruby и C #, не должны интерпретироваться как преодоление проблем необработанных указателей, таких как C, но должны рассматриваться как основанные на многих традициях - включая C, но также и на более безопасных языках, таких как Smalltalk, Simula, или Лисп.
источник
По моему опыту, указатели ВСЕГДА были сложной концепцией для многих людей. В 1970 году в университете, в котором я учился, был Burroughs B5500, и мы использовали Extended Algol для наших программных проектов. Аппаратная архитектура была основана на дескрипторах и некоторых кодах в верхней части слов данных. Они были специально разработаны, чтобы массивы могли использовать указатели, не допуская, чтобы они уходили с конца.
Мы провели оживленную дискуссию в классе о справочнике «имя против значения» и о том, как работают массивы B5500. Некоторые из нас получили объяснение немедленно. Другие не сделали.
Позже, это было несколько шокирующим, что аппаратное обеспечение не защитило меня от неуправляемых указателей - особенно на языке ассемблера. На моей первой работе после окончания учебы я помог исправить проблемы в операционной системе. Часто единственной документацией, которую мы имели, была распечатанная аварийная свалка. Я разработал умение находить источники неуправляемых указателей в дампах памяти, поэтому каждый дал мне «невозможные» дампы, чтобы разобраться. Больше проблем, которые мы имели, были вызваны ошибками указателя, чем любой другой тип ошибки.
Многие из тех, с кем я работал, начали писать на Фортране, затем перешли на С, написали на С, который очень похож на Фортран, и избегали указателей. Поскольку они никогда не усваивают указатели и ссылки, Java создает проблемы. Часто программистам на Фортране сложно понять, как на самом деле работает назначение объектов.
Современные языки сделали намного проще делать вещи, которые нуждаются в указателях «под капотом», сохраняя при этом нас от опечаток и других ошибок.
источник