@
ipwx > CLion + CMake + C++17 +
https://conan.io/愣是凑出这么多比 C++ 设计质量更翔的组合来体现 C++ 的可用性还真是辛苦了。
(虽然确实不是没法用……忽略一些实现问题的话。)
网络连接不稳定,实现随便出点 bug,调起来是爽到飞起。
> 4 、template <typename Fn> void someWrapper(const Fn& fn)。
这是哪年的新特性。
@
ericgui C++11 就允许 GC,但是没见过有厂商实现,然后最近(?)被移除了。
你说啥原因。
@
likefly @
byte10 能先别把冷启动响应和内存占用开除出性能么。
就算解决了这些问题,这里所谓的性能怕还是被 luajit 甚至 pypy 吊着打。
JIT 后性能飞起? Chez 说话了? Cling 说话了?轮得到你 JVM 跳脸?先在路线上干翻自家 Graal 再说吧。
@
wangxn 性能丰富?地球上不可能找出另一个特性比它更丰富的语言?
原来我整的一坨火星语言?
随便抓过来个 spec 来自己随手往上加个新特性,你这就得自觉呵呵了。(别说加不了,先不提经手的到处都是 C# 涵盖不了特性的语言,光个 PTC 就够大部分 CLR 系语言魔改起来吃一壶了。)
而且好死不死,恰恰你 C# 比起业界大部分语言,在这里还就是说不上话的屌丝(虽然还是可以欺负下 Rust )。
说实话,改个 C++ 成 C++/CLI 都没新造个出来那么费事。然鹅 ECMA-334 落后实际实现几年了?就微软这个 finalizer 和 destructor 傻傻分不清还是恶意卖萌(然后被 ECMA 明确打脸)的破烂文档质量还是别指望能当 spec 了。
@
levelworm 如果真不确定,那么你需要实际是 owner count >= 1 的 affine type 。
这东西因为类型系统的叒鸡,C++ 表达不出来,要么就得 template<typename T> using 管它叫我特么不知道叫什么也懒得赐名的_ptr = variant<unique_ptr<T>, shared_ptr<T>>; 去近似,还不如直接 typename<typename T> using XXX = shared_ptr<T>; 得了。
前提是你真不确定,而不是滥用——像明明业务逻辑上就没 share 的没事非得 shared_ptr 。要知道 shared_ptr 没法随便 release,污染接口可能没法收场,所以设计上能不用就不用,更不用提落实到代码的实现了。
T* 说白了无非是 variant<unique_ptr<T>, observer_ptr<T>, xxxx_iterator<T>, ...> 的大杂烩嘛,这种不确定明显更欠扁,设计中几乎从来就应该拒绝出现(古董 API 中的 T* 对应的设计中,原则上也不会有这种东西,只是因为当年的语言连 shared_ptr 这种都没法明确表达又非得要用而不得不这样变通,才会让用户习惯于 T* 很正常,形成了错觉)。就算一时稀里糊涂真不确定也得 using 个 alias 出来,这样在新代码里只要看到(为了兼容历史包袱外的) T* 就可以放心视为写 bug 直接打死,而不用浪费时间多 review 了。
@
ysc3839 因为烧饼 SysV base ABI 设计者的关系,使用 Itanium ABI 的主流实现中 default_delete 的 unique_ptr 不能直接寄存器传参,会有附加开销,除非指望 [[clang::trivial_abi]] 之类的魔法。(实际环境嘛,因为二进制兼容性,你懂的。)
严格来讲这不是 C++ 的错,但是这锅扣在把 C++ 变得更烂的用户的脑袋上十有八九不会冤枉好人。
@
zxCoder> 话虽如此,但我总觉得这两类之间可以不用分的这么清
然而实际上 C++ 和它们区别没那么大,所以本来就没那么清。
有区别的是 LLVM IR 之类。
> 比如能不能我也是从食材,厨具,烹饪手法都自己入手细调,但最终又不需要我自己实际动手,美团会给我做好送来
饭要一口一口吃。你确定现在的材料已经能让用户自己细调到位了?
事实上,C++ 所谓的细调明显是不合格的。否则也不会那么多用户不爽了,调一下魔改一下就好了嘛。
什么叫细?首先一个明显的表现是允许用户自己组合基本的特性,排除明显出问题的傻大黑粗。比如你作为用户看一个类型系统规则(因为语言作者抽风的屎设计)不爽,就该应当允许用可移植的方式替换掉,甚至把类型系统整个推翻掉取而代之,而不是先想破头把烂设计给干掉效果还烂(比如 C++ 式的类型擦除)。光考虑这点,所有钦定类型系统设计的语言(当然包括 C++ 在内的所有明确了类型规则的所谓静态类型系统的语言),都算不上能细调到哪去。
另一个例子,嫌弃所有钦定 GC 的语言,主要是因为有 GC 的语言原则上没法让用户干掉或者自己换一个,而不是什么性能原因(说到底对有本事改语言的用户,性能都是实现细节,因为严格意义的系统性能建模的理论几乎就是空白,语言规则根本无从提供保证)。这里算是 C++ 为数不多的还算能比较体现优势的地方。但类似的个别的差异虽然很重要,仍不足以拉开跟大多数类似缺陷语言的差距。
局部一点的设计,C++ 也是各种问题。像上面不止一个人就不爽 coroutine 这种半成品,你细一点真要面向库作者,好歹搞个 continuation 什么的吧。
……不多展开了,反正就算在这里痛打落水狗 WG21 也不会有啥感觉。
@
wutiantong @
junkun> 也许说 UB 确实不准确,但是问题就在于 c++并不阻止你使用再次使用 moved 的对象,即使它有潜在的问题。就像 c++不阻止你再次使用 deleted 的指针。虽然某些次运行不会出错,但是总有出错的时候。
> 所以养成好习惯很重要,微软都有推荐用 SAFE_DELETE 置空 deleted 对象指针。也有推荐 reset 掉 std::move 后的野内存。
SAFE_DELETE 也是坏习惯,而且有会让代码变烂跳脸 no overhead 的实际风险。
好习惯是你不要惦记用过的废弃物,也不要有机会让别人误用。不管是指望编译器还是规约提醒用户显式标注,都是惦记。
要解决这里的错误风险需要完全地别名分析。内部实现就罢了,要求用户完全地人肉分析接口上出现的别名是个馊主意,根本上破坏了关注点分离——还让不让人用类型签名表达 API 了?这个意义上,C++ 的名义类型比 Rust 的结构化类型检查更符合大多数场景的设计的需要,但这也意味着完全的静态检查在理论上就不可能被依赖。
另一方面,对错误的静态归类已经产生了一些问题。Rust 的内存安全和传统方式一样不负责杜绝内存泄漏,也没在类型系统中要求这种检查,而这同样是原则上无法只知道接口的签名时完全地静态检查的(要检查循环依赖基本差不多也就是 GC 了,静态就别指望了,这里不怂不会需要有什么 Rc )。而对最终用户来讲,不受控的内存泄漏未必比 UAF 之类的 UB 破坏小,所以实际上无法坐视不理。这个意义上,Rust 的双标给语言的用户带来的错觉会更加有不可控的风险。
背后的一个根本理由是,所有权语义是设计上应该几乎就全都应该静态明确的良定义规则,不可能只在具体代码实现中检查,需要检查也不可能只依赖编译时静态检查,更不应该有用户扔给工具就自己什么都不管的馊主意。要真这样,也甭吹 Rust 的类型检查,指望以后足够强力 GC 自动修正所有权就行了;然而 GC 当然不是强 AI,不可能彻底猜透代码之前的原始设计意图,撑死就是启发式半桶水瞎蒙最概然策略——还经常猜错。静态类型检查规则对此一样无能为力,只不过少了 GC 的自作聪明,能让用户干预,而在一般意义上更正确罢了。
这是方法论问题。
另外的一点上面提过,一个设计得能足够细调的语言,至少我是不怕缺特性的,大不了我自己加。
正因为 C++ 这方面设计不咋地,才没法让我通过写可复用的 C++ 代码(库)来方便地在上面加一个 affine type checker,实质上能把 C++ 改成看起来在这里和 Rust 差不多的东西(假设目的暂时只有这个)。
然而 Rust 就算自带了,这些功能一样没法单靠用户无中生有,而是得在语言规则里写死,因此也没法直接扩展:姑且假设 Rust 莫须有 spec,这 spec 中描述类型检查的显然会用英语混杂某种一阶语言去写,而不是 Rust 代码自举——所以要扩展就得提 RFC 之类和有本事维护语言规则和实现扯皮以后才可能实现。这跟往 C++ 里添加或修改特性,要跟 WG21 撕一样,没啥本质区别。
于是和 C++ 的差别就是,Rust 现在就多出来一些开箱即用的检查。然而这些东西上面不止一个人提过,对真正理解所有权的用户来讲,帮助并不明显;但是不提其中的错觉对其它用户的误导,多出来的编译性能开销是实打实的,谁都跑不掉。所以自然不能指望 C++ 熟练工对 Rust 脸色会好哪去。虽然类型系统的设计也许是个有趣的地方,用编译器给其他连 C++ 都不熟练的用户塞抹布节约 review 时间也可能体验比较愉悦,但真愿不愿意自己多花实现让代码更看起来 Rusty 实际自己又明白没提升啥可读性(就这些群魔乱舞的语法,降低的可能都不小)没让代码更健壮甚至都未必更清晰地现实意图,就是另一回事了。
这个意义上,两者各有千秋,却还是菜鸡互啄罢了。
@
piping 哪里错了?(给全上下文了?)
比编译器不报错的问题更大的是逮住什么东西就指望实现报错。
什么叫“错”,这些用户却习惯性逃避了。
(这个意义上,顺带鄙视下设计出不允许 UB 的通用语言的方法论。)
@
lesismal C++ 只要看两三百页 spec 就能上手了(除非你愿意去盯着 proposals ),篇幅而计比 Java 还省事点(这还是已经排除了框架什么的实际吃饭技术的),不知道你们看 non-normative text 读完多少书才算有懂基础这种智商税是怎么形成的。
这种语言方面的书的内容,基本全是熟练用户自己会了以后就自然知道的,也就菜鸡乐于消化别人的代谢产物了……
相比之下,Rust 因为没 spec,反而麻烦了……有时候还得盯实现。。。
提收益率的时候注意一下,你去学习一门语言,当然不只是用这个语言去写代码。
在教育语言的设计能够如何蠢以及如何比下有余比上不足来讲,C++ 无疑比绝大多数只会拎过来特性一大抄语言优秀多了。( Rust 也算还行。)