Аргумент функции в качестве ссылки, чтобы избежать проверки на НУЛЬ

#c #pointers #reference

#c #указатели #ссылка

Вопрос:

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

 void Foo(const somePointer* ptr)
{
  if (ptr == NULL)
  {
    // Throw assertion
    return;
  }

  // Do something
}
  

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

 void Foo(const somePointeramp; ptr)
{
  // No need to check anymore, client is responsible

  // Do something
}
  

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

Ответ №1:

Что ж, если вы никогда не захотите передавать несуществующий объект, используйте ссылку (Примечание: несуществующий, а не недействительный).
Если вам нужна такая возможность, используйте указатель.

Ответ №2:

Многое зависит от формы вашего кода — если вы пишете много подобного:

 A * a = new A();
f( a );
  

тогда для f () кажется разумным принимать указатель, а не записывать:

 f( *a );
  

Лично я почти никогда не проверяю наличие нулей, new не может вернуть ни одного, и если вы обнаружите, что он у вас есть, вы, вероятно, уже находитесь на территории UB.

Ответ №3:

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

Если вы внесете изменение, все, что произойдет, это то, что какой-нибудь пользователь изменит этот код:

 somePointer *ptr = something();
Foo(ptr);
  

К этому:

 somePointer *ptr = something();
Foo(*ptr);
  

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

Это полезно в качестве документации, поскольку, возможно, когда они вводят * символ, они подумают: «О, подождите, лучше бы это не было null». Тогда как, если все, что вы сделали, это задокументировали, что null является недопустимым вводом (как, скажем, strlen делает), тогда им пришлось бы прочитать документацию, чтобы знать, что не следует передавать нулевой указатель. Теоретически, пользователь вашего кода будет проверять документы вместо того, чтобы просто стучать по клавиатуре своим лицом, пока у него не появится что-то компилируемое, и предполагать, что это сработает. На практике у всех нас бывают не самые разумные моменты.