NULL 直接传递给需要 const 引用参数的函数 (VC++ 4.2)
我正在查看在旧代码库中发现的东西,我很困惑。
这是一个函数定义:
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();
? 无论如何,我可能会在那里放置一个防护装置,并让编译器在不必要的情况下将其删除,但我很想弄清楚这是如何发生的!
谢谢。
I am looking at something that I discovered in an old code base, and I am pretty confused.
Here is a function definition:
void vUpdateSequenceDetailsAndIncrement(
const CallEvent& roCPEvent,
const CallInfo& roCallInfo,
BOOL bCreationEvent);
Here it is being called:
vUpdateSequenceDetailsAndIncrement(roCPEvent, NULL, FALSE);
Here NULL is being passed directly to the reference parameter roCallInfo
. This function eventually calls:
vTimeChange(*pSeqDetails, roCPEvent, roCallInfo);
which is defined:
void vTimeChange(const SequenceDetails& roSequenceDetails,
const CallEvent& roCPEvent,
const CallInfo& roCallInfo)
Again passing the possibly NULL value to roCallInfo
. I thought that NULL could not be passed as a reference? Does anyone know if VC++ 4.x had some kind of problem which made this kind of code okay? If NULL can be passed as a reference then what happens when in vTimeChange something like this happens:
roCallInfo.getCallStartTime();
Is that not a dereference of NULL in the same way as if I were to do
CallInfo * info = NULL;
info->getCallStartTime();
?
I'll probably put a guard in there anyways and let the compiler remove it if unnecessary, but I'd love to get to the bottom of how this is happening!
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
取决于 VC 4.2 中 NULL 的定义方式,
如果是的话
,您实际上就在幕后得到了这个:
并且 CallInfo 类型的临时变量的引用被传递给函数(如果 CallInfo 有兼容的 ctor)
Depends on how NULL is defined in VC 4.2
If it is just
then you are actually getting this under the hood:
and reference of temp var of type CallInfo is passed to the function (if CallInfo has compatible ctor)
我认为
NULL
无法作为引用传递?有效引用不能为 null,但无效引用可以为 null。
您在这里看到的是无效参考。
引用不能为 null 的事实并不意味着引用在某种程度上比指针更安全,正如您在本例中看到的那样。程序可能会通过多种方式导致无效引用,您的代码就是这样的一个例子。
参考维基百科:
事实上,还有一些
引用
可能会以无效
开始。因为引用通常被实现为底层指针,所以在指针解引用表达式上初始化引用通常由编译器实现为从指针到引用的底层指针的简单赋值。因此,如果您有一个NULL
指针或指向内存中无效位置的指针,那么您实际上将拥有一个指向 NULL 或无效位置的引用。 C++ 纯粹主义者会争辩说,从技术上讲,取消引用 NULL 或无效指针无论如何都会导致未定义的行为,因此这并不违反上面的断言,即引用不能为 null 或指向内存中的任意位置。然而,这忽略了这样一个事实:在这种情况下,底层实现只是简单地执行了一次“赋值”,并没有涉及到内存位置的访问,所以这种引用的初始化通常不会引起问题,程序员必须意识到实际程序中事实上的“无效”引用的可能性。使用无效引用
roSequenceDetails
最终会导致未定义的行为。I thought that
NULL
could not be passed as a reference?A valid reference can't be null, but an invalid one can be null.
What you have here is an Invalid Reference.
The fact that a reference can't be null does not mean that references are somehow safer than pointers, as you see here in this case. There can be many ways in which an program may lead to Invalid References, Your code is one such example.
Reference Wikipedia:
There are also de facto ways that a
reference
can start outinvalid
. Because a reference is usually implemented as an underlying pointer, initializing a reference on a pointer-dereferencing expression, will usually be implemented by the compiler as a simple assignment from the pointer to the underlying pointer of the reference. Thus, if you have aNULL
pointer or a pointer pointing to an invalid location in memory, you will de facto have a reference that points to NULL or an invalid location. C++ purists would argue that, technically, dereferencing a NULL or invalid pointer leads to undefined behavior anyway, so this does not violate the assertions above that a reference cannot be null or point to arbitrary places in memory. However, this ignores the fact that in this case, the underlying implementation simply performs an "assignment", and there is no access of the memory location involved, so this initialization of the reference usually does not cause problems, and programmers must be aware of the possibility of a de facto "invalid" reference in a real program.Using the Invalid Reference
roSequenceDetails
would eventually lead to an Undefined Behavior.如果
pSeqDetails
为 null,则表达式*pSeqDetails
会导致未定义的行为。任何事情都可能发生。大多数实现不会进行任何特定的检查;你的代码似乎可以工作,直到你做了一些实际需要该对象的事情,然后它就会失败。但实施可能会导致它立即失败。The expression
*pSeqDetails
results in undefined behavior ifpSeqDetails
is null. Anything can happen. Most implementations don't make any particular checks; your code will seem to work until you do something that actually requires the object, then it will fail. But an implementation could cause it to fail immediately.