По сути, указатель - это объект, который ссылается на другой объект. В большинстве языков программирования (я полагаю) указатель - это просто число, которое относится к адресу памяти. Необработанные указатели Rust - это просто адреса памяти. В Rust есть и другие типы указателей (&
ссылки, Box
, Rc
, Arc
), для которых компилятор может проверить, является ли память действительной и содержит ли она то, что, по мнению программы, она содержит. Это не относится к необработанным указателям; в принципе они могут указывать на любую область памяти, независимо от содержимого. См. Книга для получения более подробной информации.
Сырые указатели могут быть разыменованы только внутри unsafe
блоков. Эти блоки позволяют программисту сказать компилятору: « Я лучше вас знаю, что это безопасно, и я обещаю не делать глупостей ».
Обычно лучше избегать необработанных указателей, если это возможно, потому что компилятор не может рассуждать об их допустимости, что в целом делает их небезопасными. Вещи, которые делают необработанные указатели небезопасными, могут ...
- получить доступ к пустому указателю,
- доступ к висячему (освобожденному или недействительному) указателю,
- освободить указатель несколько раз,
Все эти точки сводятся к разыменованию указателю. То есть использовать память, указанную для.
Однако использование необработанных указателей без разыменования совершенно безопасно. Это имеет смысл в том случае, если две ссылки указывают на один и тот же объект:
fn is_same(a: &i32, b: &i32) -> bool {
a as *const _ == b as *const _
}
Другим вариантом использования является интерфейс внешней функции (FFI). Если вы оберните функцию C, которая принимает необработанные указатели в качестве аргументов, вы не сможете предоставить их функции. Это на самом деле небезопасно (как и весь бизнес FFI), потому что функция может разыменовать указатель. Это означает, что вы несете ответственность за то, чтобы убедиться, что указатель действителен, остается действительным и не освобождается несколько раз.
Наконец, необработанные указатели используются для оптимизации. Например, итератор слайса использует необработанные указатели в качестве внутреннего состояния. Это быстрее, чем индексы, потому что они избегают проверок диапазона во время итерации. Однако это также небезопасно в том, что касается компилятора. Автору библиотеки нужно уделять дополнительное внимание, поэтому использование необработанных указателей для оптимизации всегда сопряжено с риском появления ошибок памяти, которых у вас обычно нет в ржавчине.
В итоге, три основных использования необработанных указателей:
- «просто цифры» - вы никогда не получите доступ к той памяти, на которую они указывают.
- FFI - вы передаете их за пределы Rust.
- ввод-вывод с отображением в память - для запуска действий ввода-вывода вам необходим доступ к аппаратным регистрам по фиксированным адресам.
- производительность - они могут быть быстрее, чем другие параметры, но компилятор не будет обеспечивать безопасность.
Что касается , когда необработанные указатели должны быть использованы, первые три пункта являются прямыми: вы будете знать, когда они применяются, потому что вы должны. Последний пункт более тонкий. Как и во всех оптимизациях, используйте их только тогда, когда выгода превышает риск и риск их использования.
Пример счетчика, когда не для использования необработанных указателей - всякий раз, когда другие типы указателей (&
ссылки, Box
, Rc
, Arc
) выполняют работу.