Это - хорошая практика программирования, чтобы всегда проверить на нулевых указателей перед использованием объекта в C++?

Это походит на большую работу; для проверки на пустой указатель каждый раз, объект используется.

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

Просто задавшись вопросом, что здесь думает сообщество?

10
задан BalusC 10 August 2010 в 21:26
поделиться

9 ответов

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

Хорошей практикой является проверка на null в параметрах функции и других местах, где вы можете иметь дело с указателями, которые вам передает кто-то другой. Однако в вашем собственном коде могут быть указатели, которые, как вы знаете, всегда будут указывать на действительный объект, поэтому проверка на null, вероятно, излишняя ... просто используйте свой здравый смысл.

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

18
ответ дан 3 December 2019 в 13:54
поделиться

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

Если функция используется внутри компании, и я знаю, как я ее использую, я не проверяю нули, так как это сделает код слишком запутанным.

2
ответ дан 3 December 2019 в 13:54
поделиться

Нет. Вместо этого вы должны сначала убедиться, что указатели не были установлены в NULL. Обратите внимание, что в Стандартном C ++:

int * p = new int;

p никогда не может быть NULL, потому что new вызовет исключение, если выделение не удалось.

Если вы пишете функции, которые могут принимать указатель в качестве параметра, вы должны обращаться с ними следующим образом

// does something with p
// note that p cannot be NULL
void f( int * p );

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

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

12
ответ дан 3 December 2019 в 13:54
поделиться

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

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

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

1
ответ дан 3 December 2019 в 13:54
поделиться

Я полагаю, что могу провести множество проверок указателей NULL за счет (отладки) только одного segfault.

И снижение производительности незначительно. ДВЕ ИНСТРУКЦИИ. Проверить регистр == ноль, перейти в случае успеха. В зависимости от машины может быть только ОДНА инструкция, если загрузка регистра устанавливает коды условий (а некоторые так и делают).

1
ответ дан 3 December 2019 в 13:54
поделиться

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

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

Кроме того, когда вы чувствуете необходимость проверить, является ли указатель NULL, вам, вероятно, следует более четко определить, кому принадлежит указатель / объект.

Кроме того, вам никогда не нужно проверять, возвращает ли new NULL, потому что он никогда не вернет NULL. Он вызовет исключение, если не сможет создать объект.

4
ответ дан 3 December 2019 в 13:54
поделиться

Другие (AshleysBrain и Нил Баттерворт) уже ответили правильно, но я резюмирую его здесь:

  1. Используйте как можно больше ссылок
  2. Если используя указатели, инициализируйте их либо значением NULL, либо допустимым адресом / объектом памяти
  3. При использовании указателей всегда проверяйте, являются ли они NULL перед их использованием
  4. Используйте ссылки (снова) ... Это C ++, а не C.

Тем не менее, есть один угловой случай, когда ссылка может быть недействительной / NULL:

void foo(T & t)
{
   t.blah() ;
}

void bar()
{
   T * t = NULL ;
   foo(*t) ;
}

Компилятор, вероятно, скомпилирует это, а затем при выполнении код выйдет из строя на t.blah () (если T :: blah () так или иначе использует this ).

Тем не менее, это мошенничество / саботаж: автор функции bar () разыменовал t без проверки t НЕ был нулевым. Таким образом, даже если сбой происходит в foo () , ошибка находится в коде bar () , а автор bar () несет ответственность .

Итак, да, используйте как можно больше ссылок , знайте этот угловой случай и не беспокойтесь о защите от саботажных ссылок ...

И если вам действительно нужно использовать указатель в C ++, если вы не на 100% уверены, что указатель не равен NULL (некоторые функции гарантируют такое), всегда проверяйте указатель.

1
ответ дан 3 December 2019 в 13:54
поделиться

Если указатели приходят к вам как параметры функции, убедитесь, что они действительны в начале функции. В остальном особого смысла нет. new вызывает исключение в случае ошибки.

0
ответ дан 3 December 2019 в 13:54
поделиться

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

0
ответ дан 3 December 2019 в 13:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: