Немного странно, что ответ, помеченный как «ответ» в этой теме, фактически выдвигает на первый план проблему с нулем, а именно:
Я также обнаружил, что большая часть моего NULL
ошибки указателя вращаются вокруг
функции от забыть проверить
возврат функций из string.h,
где NULL используется в качестве индикатора.
Не было бы неплохо, если бы компилятор мог перехватывать подобные ошибки во время компиляции, а не во время выполнения?
Если вы использовали ML-подобный язык (SML, OCaml, SML и F # в некоторой степени) или Haskell, ссылочные типы не обнуляются. Вместо этого вы представляете «нулевое» значение, заключая его в тип параметра. Таким образом, вы фактически изменяете тип возвращаемого значения функции, если она может возвращать значение null в качестве допустимого значения. Итак, допустим, я хотел вытащить пользователя из базы данных:
let findUser username =
let recordset = executeQuery("select * from users where username = @username")
if recordset.getCount() > 0 then
let user = initUser(recordset)
Some(user)
else
None
Поиск пользователя имеет тип val findUser : string -> user option
, поэтому возвращаемый тип функции фактически говорит вам, что она может возвращать нулевое значение. Чтобы использовать код, вам нужно обработать случаи Some и None:
match findUser "Juliet Thunderwitch" with
| Some x -> print_endline "Juliet exists in database"
| None -> print_endline "Juliet not in database"
Если вы не обрабатываете оба случая, код даже не скомпилируется. Таким образом, система типов гарантирует, что вы никогда не получите исключение с нулевой ссылкой, и гарантирует, что вы всегда обрабатываете нулевые значения. И если функция возвращает user
, она гарантированно является действительным экземпляром объекта. Awesomeness.
Теперь мы видим проблему в примере кода OP:
class Class { ... }
void main() {
Class c = new Class(); // set to new Class() by default
// ... ... ... code ...
for(int i = 0; i < c.count; ++i) { ... }
}
Инициализированные и неинициализированные объекты имеют одинаковый тип данных, вы не можете различить их. Иногда может быть полезен шаблон нулевого объекта , но приведенный выше код демонстрирует, что компилятор не может определить, правильно ли вы используете ваши типы.