NULL直接传递给需要const引用形参的函数(vc++ 4.2)

NULL passed directly to a function expecting a const reference parameter (VC++ 4.2)

本文关键字:函数 形参 vc++ 引用 const NULL      更新时间:2023-10-16

我正在看一些我在旧代码库中发现的东西,我很困惑。

下面是一个函数定义:

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();

?我可能会在那里放置一个保护,如果不需要,让编译器删除它,但我很想了解这是如何发生的!

谢谢。

取决于vc4.2中NULL的定义

如果只是

#define NULL 0 

那么你实际上得到了这个:

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

和CallInfo类型的临时变量的引用传递给函数(如果CallInfo有兼容的变量)

我以为NULL不能作为参考传递吗?

有效的引用不能为空,但无效的引用可以为空。
这里是一个无效引用

引用不能为空并不意味着引用在某种程度上比指针更安全,正如你在这里看到的那样。程序可能导致无效引用的方式有很多种,您的代码就是这样一个例子。

参考维基百科:
事实上,reference也可以从invalid开始。由于引用通常作为基础指针实现,因此在指针解引用表达式上初始化引用通常由编译器实现为从指针到引用的基础指针的简单赋值。因此,如果您有一个NULL指针或指向内存中无效位置的指针,您实际上会有一个指向NULL或无效位置的引用。c++纯粹主义者认为,从技术上讲,解引用NULL或无效指针无论如何都会导致未定义的行为,因此这并不违反上面的断言,即引用不能为空或指向内存中的任意位置。然而,这忽略了这样一个事实:在这种情况下,底层实现只是执行一个"赋值",并且不涉及对内存位置的访问,因此引用的这种初始化通常不会引起问题,程序员必须意识到在实际程序中存在事实上"无效"引用的可能性。

使用无效引用 roSequenceDetails最终会导致未定义行为

如果pSeqDetails为空,则表达式*pSeqDetails将导致未定义的行为。任何事情都有可能发生。大多数实现不做任何特别的检查;你的代码似乎可以工作,直到你做一些真正需要这个对象的事情,然后它就会失败。但是一个实现可能会导致它立即失败。