有趣的 C++ 代码片段,有啥解释吗? [复制]
Posted
技术标签:
【中文标题】有趣的 C++ 代码片段,有啥解释吗? [复制]【英文标题】:Interesting C++ code snippet, any explanations? [duplicate]有趣的 C++ 代码片段,有什么解释吗? [复制] 【发布时间】:2010-09-23 15:45:19 【问题描述】:可能重复:Why am I able to make a function call using an invalid class pointer
class B
public:
int i;
B():i(0)
void func1()
cout<<“func1::B\n”;
void func2()
cout<<“i = “<<i;
;
int main()
B *bp = new B;
bp->func1();
delete bp;
bp = NULL;
bp->func1();
bp->func2();
return 1;
输出:
func1::B
func1::B
Runtime Exception:
NULL pointer access
【问题讨论】:
代码无法编译:没有包含,main()
被错误声明。它确实 NOT 什么都不返回;它返回一个int
。
哇,它变成了社区维基。
显式取消引用 NULL ptr 有什么有趣的地方?
int main
仍然是无效的方法声明/语法错误。
不,int main()
是标准的。编辑:我认为之前的评论是在抱怨之前的修订中缺少括号。
【参考方案1】:
这是NULL
(或无效)对象指针的老故事;对于标准,在 NULL
对象指针上调用方法会导致未定义的行为,这意味着,就标准而言,它可以正常工作,它可能会炸毁计算机或杀死一些随机的人。
这里发生的事情是 C++ 编译器对类的典型实现的结果:类通常实际上是只包含字段的结构,所有方法实际上都是函数,它们将 this
指针作为隐藏参数。
现在,在这种实现中,如果您使用NULL
this
指针调用方法,如果它不访问任何字段,它实际上不会取消引用this
,所以它应该运行良好(就像func1
一样)。
相反,如果该方法尝试访问任何字段(例如func2
),它将取消引用this
指针,该指针是NULL
,将导致崩溃(取消引用NULL
指针再次是未定义的行为,但通常会导致崩溃)。
请注意,如果您调用的方法是虚拟的,那么几乎可以肯定,使用 NULL
this
指针调用它们会导致崩溃,因为虚拟调用是通过 vtable(函数指针数组),隐藏在类的开头。
顺便说一句,void main()
不是标准的;它应该是 int main()
(argv
和 argc
是可选的)。
【讨论】:
谢谢,我发现您的解释对帮助我理解 sn-p 中的有趣内容非常有用。【参考方案2】:当代码被修复编译时,结果是合理的。
func1()
没有引用该类的任何成员,因此它没有发现它有一个空指针作为this
使用; func2()
确实引用了 this->i
,因此当 this
为空时失败。
严格来说,这是未定义的行为 - 任何事情都可能发生。但核心转储或运行时异常是对该特定错误的最常见响应之一。
【讨论】:
+1 确实。删除对象后,对其原始成员的任何访问都会导致意外行为,具体行为可能因您使用的编译器而异。【参考方案3】:有什么好玩的?第一个输出是正确的。第二个未定义的行为。第三个是尝试访问包含在现在不存在的类中的信息。程序正确识别它是一个 NULL 指针。
【讨论】:
【参考方案4】:不是专家意见,只是看看这个:
bp->func1() 不需要对类成员的任何访问 - 在 Java 中,这最好定义为静态。也许编译器正在内联函数?
【讨论】:
【参考方案5】:您正在删除 bp 然后尝试从中调用,因为那里没有对象,实际上您已将引用设置为 null 存在运行时异常。
这样想:
您已经告诉编译器任何实例都不需要空间,因此当它尝试使用变量“i”时,它没有存储在任何有意义的地方并且程序失败。因为您已将引用设置为 null,所以程序会在执行此操作之前提前捕获它。
【讨论】:
【参考方案6】:我认为严格来说,对 bp->func1() 的第二次调用应该已经崩溃,但是通过输出调用它仍然使用分配的 bp(但现在是 NULL),也许是一些错误的编译器优化(?)。然后在 bp->func1() 调用中它真的崩溃了,因为成员 i 不可访问。
【讨论】:
【参考方案7】:从您在使用 delete 后使用指针的位置开始,您进入“未定义行为”区域。
因此,超出这一点的任何行为都依赖于编译器实现,即使“看起来可行”也必须被视为错误。
【讨论】:
以上是关于有趣的 C++ 代码片段,有啥解释吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章