Являются ли указатели плохими?

Я программирую на С++ прямо сейчас, и мне нравится использовать указатели. Но кажется, что другие, более новые языки, такие как Java, С# и Python, не позволяют явно указывать указатели. Другими словами, вы не можете писать как int x, так и int * y, а x - значение, а y - указатель на любом из этих языков. Каковы причины этого?

Ответы

Ответ 1

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

Нет ничего плохого в указателях. Идите и любите их.

В вашем примере, почему вы хотите, чтобы x и y указывали на одну и ту же память? Почему бы просто не называть его x?

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

Ответ 2

Я начну с одной из моих любимых цитат Скотта Мейерса:

Когда я даю беседы об обработке исключений, я учу людям две вещи:

  • УКАЗЫВАЮТ ВАШИ ВРАГИ, потому что они приводят к тем проблемам, которые auto_ptr предназначен для устранения.

  • УКАЗЫВАЮТСЯ ВАШИ ДРУЗЬЯ, так как операции с указателями не могут выбраться.

Затем я говорю им, чтобы у них был хороший день: -)


Дело в том, что указатели чрезвычайно полезны и, безусловно, необходимо понимать их при программировании на С++. Вы не можете понять модель памяти С++ без понимания указателей. Когда вы реализуете класс владения ресурсами (например, умный указатель, например), вам нужно использовать указатели, и вы можете воспользоваться их гарантией без броска для записи исключающих класс классов владения ресурсом.

Однако в хорошо написанном коде приложения С++ вам никогда не придется работать с необработанными указателями. Никогда. Вы всегда должны использовать некоторый слой абстракции вместо прямого взаимодействия с указателями:

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

  • Используйте интеллектуальные указатели для управления любыми указателями, которые вы используете. Смарт-указатели, такие как shared_ptr, auto_ptr и unique_ptr, помогают предотвратить преждевременное утечку ресурсов или свободных ресурсов.

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

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

  • Когда вы работаете с устаревшими или сторонними API-интерфейсами, и вы абсолютно должны использовать raw-указатели, напишите класс, чтобы инкапсулировать использование этого API.

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

Ответ 3

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

Ответ 4

Истинный "указатель" имеет две характеристики.

  • Он содержит адрес другого объекта (или примитива)
    • и предоставляет числовой характер этого адреса, чтобы вы могли выполнять арифметику.

Обычно арифметические операции, определенные для указателей, следующие:

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

Управляемые языки обычно ведут вас по пути "ссылок" вместо указателей. Ссылка также содержит адрес другого объекта (или примитива), но арифметика не разрешена.

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

Вместе это обеспечивает безопасность типов, но при ужасной потере общности.

Ответ 5

Я пытаюсь напрямую ответить на вопрос OP:

Другими словами, вы не можете писать оба int x и int * y, а x - значение, а y - указатель, в любом из эти языки. Что такое рассуждение за этим?

Причиной этого является модель управляемой памяти на этих языках. В С# (или Python, или Java,...) время жизни ресурсов и, следовательно, использование памяти управляется автоматически базовой средой выполнения или ее сборщиком мусора, если быть точным. Вкратце: приложение не имеет контроля над расположением ресурса в памяти. Он не указывается - и даже не гарантируется постоянное пребывание в ресурсе ресурса. Следовательно, понятие указателя как "местоположения чего-то в виртуальной или физической памяти" совершенно не имеет значения.

Ответ 6

Как уже упоминалось, указатели могут, и на самом деле, пойти не так, если у вас есть массовое приложение. Это одна из причин, по которым мы иногда видим, что Windows имеет проблемы из-за создания NULL-указателей! Мне лично не нравятся указатели, потому что это приводит к ужасной утечке памяти и независимо от того, насколько хорошо вы управляете своей памятью, она в конечном итоге выследит вас. Я много работал с OpenCV при работе с приложениями для обработки изображений. Имея много указателей, плавающих вокруг, вставляя их в список, а затем получая их позже, вызвало проблемы для меня. Но опять же, есть хорошие стороны использования указателей, и часто это хороший способ настроить ваш код. Все зависит от того, что вы делаете, какие спецификации вы должны встретить и т.д.