Как мне проверить, является ли ссылка нулевой?

#c #operator-overloading #reference

#c #перегрузка оператора #ссылка

Вопрос:

Я хочу проверить, является ли что-то нулевым, например:

 string xxx(const NotMyClassamp; obj) {
  if (obj == NULL) {
     //...
  }
}
  

Но компилятор жалуется на это: существует 5 возможных перегрузок == .

Итак, я попробовал это:

   if (obj == static_cast<NotMyClass>(NULL)) {
  

Это приводит к сбою, потому что NotMyClass == перегрузка не обрабатывает нули.

редактировать: для всех скажите мне, что это не может быть NULL, я, конечно, получаю что-то NULL, как в моем отладчике:

введите описание изображения здесь

Комментарии:

1. obj — это ссылка, а не указатель. Вы не можете сравнить ее с NULL.

2. C — это не C или Java. Ответы здесь хороши, но вам также может быть полезно немного ознакомиться с указателями и ссылками в C .

3. Я очень сомневаюсь, что вы получите «сбой» для этого условия.

4. @Tomalak в моем отладчике я вижу, что он пытается выполнить obj.something() для этой ссылки. Это, безусловно, приводит к сбою.

5. Единственная разумная вещь, которую вы могли бы сделать, чтобы проверить наличие такого условия, — это if(amp;obj==NULL) , но это все равно не имело бы смысла, потому что, если вы получаете » NULL ссылку», это означает, что у вас есть логическая ошибка в вашем приложении (вы уже разыменовали NULL указатель для создания такой ссылки, так что вы уже находитесь в стране неопределенного поведения). Из-за этого компилятор мог бы также оптимизировать такую проверку, поскольку он знает, что NULL ссылки не существуют (как это обычно делается для NULL проверок указателей, которые уже были разыменованы).

Ответ №1:

В правильно сформированной программе C ссылки никогда не NULL (точнее, адрес объекта, на который у вас есть ссылка, может никогда не быть NULL ).

Таким образом, ответ не только «нет, нет никакого способа», следствием является «это не имеет смысла».


Ваше утверждение относительно C также не имеет смысла, поскольку C не имеет ссылок.

А что касается Java, ее «ссылки» во многих отношениях больше похожи на указатели C , включая этот.

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


Если вам нужно это поведение «необязательного объекта», тогда вы ищете указатели:

 std::string xxx(const NotMyClass* ptr) {
  if (ptr == NULL)
     throw SomeException();

  const NotMyClassamp; ref = *ptr;
  /* ... */
}
  

Но подумайте, действительно ли вам это нужно; достойной альтернативой может быть boost::optional , если вы действительно это делаете.

Комментарии:

1. Где-то дальше по стеку это указатель, и кто-то преобразовал его в ссылку. Я получаю это как ссылку. И это «NULL».

2. @deliciousirony: Программа вызывает UB в тот момент, когда пользователь разыменовал этот нулевой указатель; все, что происходит после этого, является глупостью. Вы видите утечку реализации по чистой случайности (вроде)

3. @deliciousirony: И я думаю, вы имеете в виду s/static/call stack/

Ответ №2:

То, что вы спрашиваете, не имеет смысла. Ссылки в C никогда не могут быть «нулевыми», поскольку они могут быть созданы только путем псевдонимирования существующего объекта, и они не могут быть восстановлены. Один раз ссылка на x , всегда ссылка на x .

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

Ответ №3:

Вам не нужно это проверять, поскольку ссылки в C не могут быть нулевыми. Указатели могут быть нулевыми, но вы их здесь не используете.

Ответ №4:

Как говорили другие, четко определенный код никогда не имеет нулевых ссылок, поэтому вы не несете ответственности за их проверку.

Это не означает строго, что они никогда не создаются на практике (но, надеюсь, в промежуточном, а не производственном коде). В некоторых компиляторах, хотя определенно не в стандартном C , возможно получить ссылку, адрес которой равен нулю:

 int * p = NULL;
int amp; x = *p;
  

Часто не происходит сбой (пока), хотя по стандарту C это недетерминированное поведение после второй строки. Это побочный эффект ссылок, которые обычно реализуются с помощью указателей «за кулисами». Вероятно, позже произойдет сбой, когда кто-то использует x.

Если вы пытаетесь отладить такую ситуацию, вы можете проверить, не равен ли адрес x нулю:

 #include <cassert>
// ...
assert(amp;x != NULL);
  

Комментарии:

1. 1 хороший ответ, хотя, возможно, стоит указать, что сама фраза «наличие ссылок NULL » вводит в заблуждение; мы говорим об адресе объекта (хотя и несуществующего!), на который ссылается.

Ответ №5:

Как говорили люди, ссылки в C никогда не должны быть нулевыми (NULL или nullptr), однако все еще возможно получить нулевые ссылки, особенно если вы выполняете какое-то злое приведение. (Давным-давно я делал такую вещь, когда не знал ничего лучшего.)

Чтобы проверить, является ли ссылка нулевой (NULL или nullptr), преобразуйте ее в указатель, а затем протестируйте. Итак:

 if (amp;obj == nullptr)
  

это то, что вы эффективно ищете.

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

Комментарии:

1. Это невозможно в правильно сформированной программе; ваш UB запускается в тот момент, когда вы получаете «ссылку» на объект, который не существует. Все, что после этого, является глупостью.

2. intamp; foo() { return (intamp;)*((int*)0); } Создаст нулевую ссылку, произойдет сбой, если вы попытаетесь сделать практически что угодно с возвращаемым значением, кроме как взять указатель.

3. Нет, такой вещи, как «нулевая ссылка», не существует. У вас есть программа, написанная на чем-то, что немного похоже на C , которая содержит что-то, что выглядит как ссылка на объект, который не существует.

4. Да, это недопустимо, но это все равно означает, что это может быть сделано и будет скомпилировано. Однако при запуске она завершится сбоем при первой возможности.