NULL передается непосредственно в функцию, ожидающую константный ссылочный параметр (VC ++ 4.2) - PullRequest
4 голосов
/ 07 сентября 2011

Я смотрю на что-то, что я обнаружил в старой кодовой базе, и я довольно смущен.

Вот определение функции:

void vUpdateSequenceDetailsAndIncrement(
            const CallEvent& roCPEvent,
            const CallInfo& roCallInfo,
            BOOL bCreationEvent);

Здесь это называется:

vUpdateSequenceDetailsAndIncrement(roCPEvent, NULL, FALSE);

Здесь NULL передается непосредственно в опорный параметр roCallInfo. Эта функция в конечном итоге вызывает:

vTimeChange(*pSeqDetails, roCPEvent, roCallInfo);

что определено:

void vTimeChange(const SequenceDetails& roSequenceDetails,
        const CallEvent& roCPEvent,
        const CallInfo& roCallInfo)

Снова передавая возможно значение NULL roCallInfo. Я думал, что NULL не может быть передан в качестве ссылки? Кто-нибудь знает, была ли в VC ++ 4.x какая-то проблема, из-за которой этот код был в порядке? Если в качестве ссылки можно передать NULL, то что происходит, когда в vTimeChange происходит что-то подобное:

roCallInfo.getCallStartTime(); 

Разве это не разыменование NULL таким же образом, как если бы я должен был сделать

CallInfo * info = NULL;
info->getCallStartTime();

? В любом случае, я, возможно, в любом случае поставлю там охрану и позволю компилятору удалить его, если в этом нет необходимости, но я бы хотел узнать, как это происходит!

Спасибо.

Ответы [ 3 ]

8 голосов
/ 07 сентября 2011

Зависит от того, как NULL определено в VC 4.2

Если это просто

#define NULL 0 

тогда вы фактически получаете это под капотом:

vUpdateSequenceDetailsAndIncrement(roCPEvent, CallInfo(0), FALSE);

и ссылка на временную переменную типа CallInfo передается функции (если CallInfo имеет совместимый ctor)

5 голосов
/ 07 сентября 2011

Я думал, что NULL не может быть передан в качестве ссылки?

Допустимая ссылка не может быть нулевой, но недействительная ссылка может быть нулевой.
Здесь у вас есть Неверная ссылка .

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

Справочная Википедия:
Существуют также де-факто способы, которыми reference может начать invalid. Поскольку ссылка обычно реализуется как базовый указатель, инициализация ссылки в выражении разыменования указателя обычно реализуется компилятором как простое присваивание от указателя до базового указателя ссылки. Таким образом, , если у вас есть NULL указатель или указатель, указывающий на недопустимое место в памяти, у вас фактически будет ссылка, указывающая на NULL или недопустимое местоположение . Пуристы C ++ утверждают, что технически разыменование NULL или недопустимого указателя в любом случае приводит к неопределенному поведению, поэтому это не нарушает утверждения выше, что ссылка не может быть нулевой или указывать на произвольные места в памяти . Однако это игнорирует тот факт, что в этом случае базовая реализация просто выполняет «присваивание», и нет доступа к соответствующему месту в памяти, поэтому такая инициализация ссылки обычно не вызывает проблем, и программисты должны знать об этом. возможность де-факто «недействительной» ссылки в реальной программе.

Использование Неверная ссылка roSequenceDetails в конечном итоге приведет к Неопределенное поведение.

0 голосов
/ 07 сентября 2011

Выражение *pSeqDetails приводит к неопределенному поведению, если pSeqDetails равно нулю.Все может случиться.Большинство реализаций не делают никаких конкретных проверок;ваш код будет работать до тех пор, пока вы не сделаете что-то, что на самом деле требует объекта, тогда он не будет работать.Но реализация может привести к немедленному сбою.

...