我正在观看 Alexandrescu 的视频,他的代码片段如下:
// an example implementation of a single threaded shared_ptr
~SingleThreadPtr() {
if(!c_) {
soSueMe: delete p_;
} else if(--*c_ == 0) {
delete c_;
goto soSueMe;
}
}
这里是 https://youtu.be/Qq_WaiwzOtI?t=36m44s .他说,“我使用我著名的 'goto soSueMe' 构造”,并说“尝试在没有 goto 的情况下编写这个,[..] 你会发现它很困难”。
这有什么难的?下面是不是一样,显然不难,而且更易读:
// an example implementation of a single threaded shared_ptr
~SingleThreadPtr() {
if(!c_) {
delete p_;
} else if(--*c_ == 0) {
delete c_;
delete p_;
}
}
或者甚至不一样(从而首先加强了反对 goto
的论点)?这里发生了什么样的黑客黑魔法巫术?
最佳答案
这里的重点是 shared_ptr 析构函数被相对频繁地调用,并且通常是内联的,这是一种减少内联析构函数大小的尝试(因为 goto
比 delete 调用小得多)。
例如,编译时的析构函数调用 delete p_
可能类似于:
LBB5_8:
movq -16(%rbp), %rax ## 8-byte Reload
movq (%rax), %rcx
cmpq $0, %rcx
movq %rcx, -24(%rbp) ## 8-byte Spill
je LBB5_4
movq -24(%rbp), %rax ## 8-byte Reload
movq %rax, %rdi
callq __ZdlPv
LBB5_4:
(其中 callq __ZdlPv
是最终被调用的底层对象析构函数)。
而 goto
看起来就像这样:
LBB5_8:
jmp LBB5_2
因此,通过分支而不是重复 delete p_
语句,代码大小显着减少。
This accompanying presentation可能会被证明是有用的阅读(虽然很简洁)。
关于c++ - 在 if else 链中使用 goto 有什么特别之处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35733307/