Подтвердить что ты не робот

Использует ли ссылки NULL?

Я натолкнулся на этот код:

void f(const std::string &s);

И затем вызов:

f( *((std::string*)NULL) );

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

Я не уверен, что об этом думать, это выглядит странно, но что вы думаете об этой конструкции?

4b9b3361

Ответ 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) ....