Использует ли ссылки NULL?
Я натолкнулся на этот код:
void f(const std::string &s);
И затем вызов:
f( *((std::string*)NULL) );
И мне было интересно, что другие думают об этой конструкции, она используется для обозначения того, что функция f() должна использовать какое-то значение по умолчанию (которое он вычисляет) вместо некоторого предоставленного пользователем значения.
Я не уверен, что об этом думать, это выглядит странно, но что вы думаете об этой конструкции?
Ответы
Ответ 1
Нет. Это поведение undefined и может привести к коду, чтобы что-либо сделать (включая переформатирование жесткого диска, сброс ядра или оскорбление вашей матери).
Если вам нужно пройти NULL, используйте указатели. Код, который принимает ссылку, может предполагать, что он относится к действительному объекту.
Приложение: Стандарт С++ 03 (ISO/IEC 14882, 2 nd edition 2003) гласит, что в §8.3.2 "Ссылки", пункт 4:
Ссылка должна быть инициализирована для ссылки на действительный объект или функции. [Примечание: в частности, нулевая ссылка не может существовать в четко определенной программе, поскольку только способом создания такой ссылки было бы привязать ее к "объекту", полученному путем разыменования нулевого указателя, что вызывает поведение undefined. Как описано в 9.6, ссылка не может быть привязана непосредственно к битовому полю. ]
[Полужирный текст добавлен для акцента]
Ответ 2
Иногда вы видите такие конструкции в довольно эзотерическом коде библиотеки шаблонов, но только внутри sizeof()
, где это безопасно.
Предположим, вам нужно знать размер возвращаемого типа типа типа F
, если в качестве аргумента ему была передана ссылка на тип T
(оба из них являются параметрами шаблона). Вы можете написать:
sizeof(F(T()))
Но что, если у T нет конструктора по умолчанию? Поэтому вы делаете это вместо:
sizeof(F(*((T *)0)))
Выражение, переданное в sizeof
, никогда не выполняется - оно просто анализируется до того момента, когда компилятор знает размер результата.
Ответ 3
Мне любопытно - действительно ли функция 'f' проверяет это условие? Потому что, если это не так, и он пытается использовать строку, тогда это явно сработает, когда вы попытаетесь ее использовать.
И если 'f' проверяет ссылку на NULL, тогда почему это не просто указатель? Есть ли какое-то жесткое и быстрое правило, что вы не будете использовать указатели, а некоторые костяшки будут подчиняться букве закона, не задумываясь о том, что это значит?
Я просто хотел бы знать...
Ответ 4
Использует ли ссылки NULL в порядке?
Нет, если вам не нравится ваш босс и ваша работа;)
Это что-то очень плохое. Одна из важнейших точек зрения, что это
не может быть NULL (если вы не принудительно)
Ответ 5
для случая вы можете сделать "пустой объект", который будет играть роль нулевого указателя
class Foo
{
static Foo empty;
public:
static bool isEmpty( const Foo& ref )
{
return &ref==∅
}
}
Ответ 6
Как уже говорили другие: ссылка должна быть действительной. Вот почему это ссылка вместо указателя.
Если вы хотите, чтобы f() имел поведение по умолчанию, вы можете использовать это:
static const std::string default_for_f;
void f(const std::string &s = default_for_f)
{
if (&s == &default_for_f)
{
// make default processing
}
else
...
}
...
void bar()
{
f(); // call with default behavior
f(default_for_f); // call with default behavior
f(std::string()); // call with other behavior
}
Вы можете сохранить параметр по умолчанию для f(). (Некоторые люди ненавидят параметры по умолчанию.)
Ответ 7
f( *((std::string*)NULL) );
Это по существу разыменование NULL, которое на большинстве систем # определено как 0. Последнее, что я проверил, 0x00000000 - это недействительный адрес памяти для чего-либо.
Что бы ни случилось, просто проверив
if (std::string.length() > 0) ....