Проверка несуществующий объект в C++

Я главным образом только работал с C, и сталкиваюсь с некоторыми незнакомыми проблемами в C++.

Скажем, то, что у меня есть некоторая функция как это в C, который был бы очень типичен:

int some_c_function(const char* var)
{
    if (var == NULL) {
        /* Exit early so we don't dereference a null pointer */
    }
    /* The rest of the code */
}

И скажем, что я пытаюсь записать подобную функцию в C++:

int some_cpp_function(const some_object& str)
{
    if (str == NULL)  // This doesn't compile, probably because some_object doesn't overload the == operator

    if (&str == NULL) // This compiles, but it doesn't work, and does this even mean anything?
}

В основном все, что я пытаюсь сделать, должно препятствовать тому, чтобы программа отказала, когда some_cpp_function () называют с ПУСТЫМ УКАЗАТЕЛЕМ.

  • Что является самым типичным / распространенным способом сделать это с объектным C++ (который не включает перегрузку == оператор)?

  • Это - даже правильный подход? Таким образом, разве я не должен писать функции, которые берут объект в качестве аргумента, а скорее, пишут функции членства? (но даже если так, ответьте на исходный вопрос),

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

33
задан Peter Mortensen 27 January 2016 в 13:25
поделиться

7 ответов

в основном, все, что я пытаюсь сделать, это предотвратить разбойку программы, когда uvery_cpp_function () вызывается с НУЛЕВОЙ.

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

34
ответ дан 27 November 2019 в 18:02
поделиться

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

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

То есть я видел проверку кода для «нулевых ссылок», что делает что-то вроде: , если (& ссылка == 0) , но стандарт ясно, что не могут быть нулевые ссылки в хорошо сформированном программа. Если ссылка связана с нулевым объектом, программа не связана и должна быть исправлена. Если вам нужны дополнительные значения, используйте указатели (или некоторые более высокого уровня, как Boost :: Необязательно ), а не ссылки.

6
ответ дан 27 November 2019 в 18:02
поделиться

Список ссылок C ++ Естественно не может быть нулевым, вам не нужен чек. Функция может быть вызвана только путем передачи ссылки на существующий объект.

2
ответ дан 27 November 2019 в 18:02
поделиться
  • Какой самый типичный / общий способ сделать это с объектом C ++ (который не включает перегрузку оператора ==)?
  • Это даже правильный подход? т.е. Должен ли я не писать функции, которые принимают объект как аргумент, а скорее, пишут функции членов? (Но даже если так, пожалуйста, ответьте на оригинальный вопрос.)

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

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

Если вам нужно представить «без объекта» Затем пройдите указатель на функцию, и позвольте этому указателю быть нулевым:

int silly_sum(int const* pa=0, int const* pb=0, int const* pc=0) {
  /* Take up to three ints and return the sum of any supplied values.

  Pass null pointers for "not supplied".

  This is NOT an example of good code.
  */
  if (!pa && (pb || pc)) return silly_sum(pb, pc);
  if (!pb && pc) return silly_sum(pa, pc);
  if (pc) return silly_sum(pa, pb) + *pc;
  if (pa && pb) return *pa + *pb;
  if (pa) return *pa;
  if (pb) return *pb;
  return 0;
}

int main() {
  int a = 1, b = 2, c = 3;
  cout << silly_sum(&a, &b, &c) << '\n';
  cout << silly_sum(&a, &b) << '\n';
  cout << silly_sum(&a) << '\n';
  cout << silly_sum(0, &b, &c) << '\n';
  cout << silly_sum(&a, 0, &c) << '\n';
  cout << silly_sum(0, 0, &c) << '\n';
  return 0;
}

Если «нет объекта», никогда не должен быть представлен, то ссылки на то, чтобы узнать, что работают нормально. На самом деле, перегрузки оператора намного проще, потому что они принимают перегрузки.

Вы можете использовать что-то вроде Boost :: Необязательно.

2
ответ дан 27 November 2019 в 18:02
поделиться

Как все сказанные, ссылки не могут быть нулевыми. То есть потому, что ссылка относится к объекту. В вашем коде:

// this compiles, but doesn't work, and does this even mean anything?
if (&str == NULL)

Вы принимаете адрес объекта STR . По определению STR существует, поэтому у него есть адрес. Итак, не может быть NULL . Таким образом, синтаксически вышеперечисленное является правильным, но логически, в , если состояние всегда будет ложным.

О ваших вопросах: это зависит от того, что вы хотите сделать. Вы хотите, чтобы функция была в состоянии изменить аргумент? Если да, пропустите ссылку. Если нет, не (или не передавайте ссылку на const ). См. Это FAQ C ++ для некоторых хороших деталей.

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

6
ответ дан 27 November 2019 в 18:02
поделиться

Ссылка не может быть нулевым. Интерфейс заставляет вас передавать реальный объект в функцию.

Так что нет необходимости проверять на нуле. Это одна из причин, по которым ссылки были введены в C ++.

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

14
ответ дан 27 November 2019 в 18:02
поделиться

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

Напишите свою функцию, как будто вы написали его в C.

2
ответ дан 27 November 2019 в 18:02
поделиться
Другие вопросы по тегам:

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