我正在观看Alexandrescu的视频,他有以下代码片段:
// an example implementation of a single threaded shared_ptr
~SingleThreadPtr() {
if(!c_) {
soSueMe: delete p_;
} else if(--*c_ == 0) {
delete c_;
goto soSueMe;
}
}
Run Code Online (Sandbox Code Playgroud)
这是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_;
}
}
Run Code Online (Sandbox Code Playgroud)
或者是不是一样的(从而加强了反对的论点goto)?什么样的黑客黑魔法伏都教在这里?
don*_*mus 12
这里的关键是,shared_ptr的析构函数被称为相对频繁,一般内嵌,这是为了减少内联析构函数大小(以企图goto比删除调用小得多).
例如,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:
Run Code Online (Sandbox Code Playgroud)
(callq __ZdlPv最后调用底层对象析构函数).
尽管goto看起来只是像这样:
LBB5_8:
jmp LBB5_2
Run Code Online (Sandbox Code Playgroud)
因此,通过分支而不是重复delete p_声明,代码化显着减少.
随附的演示文稿可能证明是有用的阅读(虽然简洁).