没有野猪

没有野猪

野猪教 神职人员

首先别 C/C++,我怕 >_<


理论上肯定是给编译器的信息越多,编译器做优化的余地就越大,生成的产物(不管是 IR 还是汇编还是啥别的东西)质量就越高。在几乎所有的情况下如果 C++/Rust 慢于 C ,一定是代码或者编译器写得不好。比如说如果 bounds checking 没被优化掉,那要么是编译器弱智,要么是你在瞎写没提供足够信息(比如非要模拟莫名其妙的三段式 for )。再比如说能直接用语义更清楚的方法解决问题,就比奋其私智瞎写位运算 trick 要好(后者既恶心读者又阻碍编译器识别你的意图)。此外非要在 safe 部分写本来应该塞进 unsafe 的东西就没救了,比如随便一搜就能找到的各种风味的弱智 safe 链表,明明(un)safe 生而平等,非要自断一臂……


现在大家都是针对 abstract machine 与编译器合作一起写代码的,写程序的人给编译器提供准确的语义和足够的信息然后交给它自由发挥,这样双方都开心。如果非要不相信编译器以为它就是个换皮解释器乱整「底层优化」基本是害人害己。

具体到这里(虽然没明说,但我来瞎猜一个 memcpy 和指针的可能联系:)就不说裸指针满天飞是一件多么恶心人的事了,光从正确性上来说乱 cast 小心被 strict aliasing 干爆。比起 T1 x = 🐗...; 然后拿着 *(T2*)&x 瞎玩,正常的做法是 auto y = std::bit_cast<T2>(x),然后爱怎么玩 y 就怎么玩,如果需要写回再 x = std::bit_cast<T1>(y); 此时编译器会消除掉不必要的复制,直接在原地做位运算。

(没有 bit_cast 去找编译器里面有什么 builtin/扩展可以做类似事情,这个也没有就试试 memcpy/union ,但总的思路是复制出来修改然后再塞回去,这个「复制」只发生在抽象机上以至于实际上依然等于原地操作)

(指针大师们请在编译 Linux 的时候别开-fno-strict-aliasing 再说话,谢谢)


至于 Rust 最大的优点……据我观察,有这么一类人:特喜欢「只做好一件事」的 Unix 哲学同时对指针这种恨不得一百种语义合在一起既整蛊编译器又整蛊使用者的东西赞不绝口,从来没听说过抽象机是什么东西一边抱怨-O2 出来的汇编看不懂一边大叫 C 是高级汇编,自以为特懂底层硬件然后觉得 CPU 里面直接执行的汇编 + 2022 年 x86 架构还是只有指令集里面给的那几个寄存器,分不清 undefined / unspecified / implementation-defined behavior 哪天代码爆炸了就往地上一躺开始在 mailing list 里面喷这个喷那个,以为 inline 语义是建议编译器做内联优化,认为指针就是地址,引用是指针的语法糖……如果一个语言,能自动过滤掉这类🐗,那就是功德无量,如果非要我找一个 Rust 能做但别说是现代就算是未来的 C++也不可能做到的东西,那我首选这个。