我正在看一些我在旧代码库中发现的东西,我很困惑。
这是一个函数定义:
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();
? 我可能会在那里放一个警卫,让编译器删除它,如果没有必要,但我想深究这是怎么回事!
感谢。
答案 0 :(得分:8)
取决于如何在VC 4.2中定义NULL
如果只是
#define NULL 0
然后你真的得到了这个:
vUpdateSequenceDetailsAndIncrement(roCPEvent, CallInfo(0), FALSE);
并且将CallInfo类型的temp var的引用传递给函数(如果CallInfo具有兼容的ctor)
答案 1 :(得分:5)
我认为NULL
无法作为参考传递?
有效引用不能为空,但无效引用可以为空。
你在这里有一个无效的参考。
引用不能为null的事实并不意味着引用在某种程度上比指针更安全,正如您在本例中所见。程序可能有多种方式导致无效引用,您的代码就是这样一个例子。
参考维基百科:
事实上reference
也可以从invalid
开始。{1}}。因为引用通常作为底层指针实现,所以初始化指针解除引用表达式的引用通常由编译器实现为从指向引用的底层指针的指针的简单赋值。因此,如果你有一个NULL
指针或一个指向内存中无效位置的指针,你实际上会有一个指向NULL或无效位置的引用。 C ++纯粹主义者认为,从技术上讲,取消引用NULL或无效指针会导致未定义的行为,所以这并不违反上面的断言,即引用不能为null或指向内存中的任意位置。但是,这忽略了这样一个事实:在这种情况下,底层实现只是执行“赋值”,并且没有访问所涉及的内存位置,因此引用的初始化通常不会引起问题,程序员必须知道实际程序中事实上“无效”引用的可能性。
使用无效参考 roSequenceDetails
最终会导致未定义行为。
答案 2 :(得分:0)
如果*pSeqDetails
为空,则表达式pSeqDetails
会导致未定义的行为。任何事情都可能发生。大多数实现不进行任何特定检查;在您执行实际需要该对象的操作之前,您的代码似乎会起作用,然后它将失败。但实施可能会导致它立即失败。