V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zxCoder
V2EX  ›  程序员

虽然说没有银弹,但是我感觉 c++完全可以设计成更友好,开发速度更快的语言

  •  
  •   zxCoder · 2021-07-14 21:14:58 +08:00 · 16710 次点击
    这是一个创建于 1017 天前的主题,其中的信息可能已经有所发展或是发生改变。

    c++大佬别杠我,不可否认的是 c++学起来实在太难,写起来实在太慢

    实际上很多东西感觉完全可以反过来吸收别的语言的优点

    209 条回复    2023-10-16 14:43:54 +08:00
    1  2  3  
    lesismal
        201
    lesismal  
       2021-07-21 14:48:36 +08:00   ❤️ 2
    @bluesenzhu

    rust 吹这么多年,做出什么杀手级项目来了?
    —— tidb 这些或者其他什么项目都可以按下不表,单就内核开始接受 rust 这件事,当年 cpp 也被努力过入内核、但是 cpp 没机会的


    你们都忘记了 c++在某种程度上继承了 c 语言的哲学:相信程序员
    —— 这个逻辑非常不对,你要是再往前推,打孔卡时代连编译器优化都没有、岂不更相信程序员?
    因为编程语言发展的早期,语言之父们也没有当下这么多的语言设计经验,他们已经实现了从机器语言、汇编语言中解放生产力的目标,而相信程序员——只是语言发展早期不成熟带来的错觉、副作用,或者说是当下该语言没有朝着更高阶演进、大家必须更大程度地自己去控场而“为赋新词强说愁”,为了奶 c++而给 c/c++扣上相信程序员的高帽、自欺欺人罢了

    rust 非要踩 c++上位?
    —— 这还不是 c++自己不争气,如果 c++争气,根本就不会有 rust 诞生,也不会有 go 诞生。层主可以去了解下为什么 firefox 要搞 rust 、为什么 google 要搞 go

    我不打算再入手 rust 了,也不是 rust 粉丝,但是对于宗教狂热这个词,层主可能比其他几位 rust 粉更狂热。
    nmap
        202
    nmap  
       2021-07-21 15:40:52 +08:00
    需要友好的 C++ 请学习 Rust,需要开发速度更快的 C++ 请学习 Go
    hitmanx
        203
    hitmanx  
       2021-07-21 22:29:04 +08:00
    @lesismal 纯好奇。Linux 内核正式接受 rust 了吗,有出处不?我搜了一下,比如这个是最近的新闻: https://www.zdnet.com/article/rust-in-the-linux-kernel-why-it-matters-and-whats-happening-next/ 里面提到 Linus 并未表示同意,且对于第一个 RFC 的回应不怎么 positive 。不知道是不是有更新的消息?

    And Torvalds hasn't indicated whether he would approve the pull request (PR) to merge the latest Rust for Linux patches into the main Linux kernel.

    Ojeda's first RFC included examples of Rust drivers, but Torvalds' response to the Linux drivers was not positive: he said that run-time failure panic – a type of error – is a "fundamental issue".
    lesismal
        204
    lesismal  
       2021-07-22 00:10:32 +08:00   ❤️ 1
    @hitmanx

    And Torvalds hasn't indicated whether he would approve the pull request (PR) to merge the latest Rust for Linux patches into the main Linux kernel.

    linus 也只是对这个提交中存在 panic 不满意,并且你发的链接中下文中提到恐慌问题已经解决了:

    Ojeda acknowledges Torvalds' concerns about panics, but also says the team of developers attempting to bring Rust to Linux are addressing the issues.

    He says that removing unnecessary panics is a key concern amongst the Linux kernel community, but believes that it is "mostly a technical obstacle and has been solved."


    我上面回复中说的 "开始接受” 可能不够准确,正式 merge 后可能更准确些,但估计只是时间问题

    而且,还有其他的一些的新闻,比如:
    https://www.theregister.com/2021/07/05/rust_for_linux_kernel_project/

    看副标题:
    Torvalds reckons 'it might be mergeable for 5.14'

    linus 之前的观望到对 PR 中代码问题的指正、提交人员的修复、考虑可能合并到,这个变化过程,跟 C 版提交是类似的,至少没像 c++那样连机会都不给,而是已经在走流程,只要 rust 语言自己别浪出什么幺蛾子,内核正式接受 rust 应该只是时间问题,毕竟天下苦 c/c++久矣。。。
    FrankHB
        205
    FrankHB  
       2021-07-23 21:16:43 +08:00   ❤️ 1
    @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 也算还行。)
    levelworm
        206
    levelworm  
       2021-07-23 21:56:37 +08:00
    @FrankHB

    @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 了。

    多谢多谢,我觉得我的问题还是学艺不精,毕竟是业余的,写代码往往写一会就不写了,等过了几个礼拜再写。目前写的多了点,我觉得等我写的多了点就能好一些。
    byte10
        207
    byte10  
       2021-07-25 08:31:46 +08:00
    @FrankHB 相信我的 JIT 性能是飞起,直接干掉 C++(虽然 java 也是 C++写),你听话就好了,不要老是自以为是,相信我。你要去做一些科学实验。
    wangxn
        208
    wangxn  
       2021-07-26 22:16:25 +08:00
    @FrankHB 你这副不可一世的嘴脸完美诠释什么叫做“一桶水摇不响,半桶水响叮当”。你是不是觉得自己半懂不懂的在这指点江山,别人就会觉得高明之极?
    老实说你回我的那几句话肤浅至极,前言不搭后语兼语无伦次,简直不值一驳。
    先了解下 C# 有什么特性再来这里大放厥词吧。
    P.S. 我工作中也主要用 C++,不用你教我 C++ 有什么 C# 没有的功能,你应该了解下 C# 有什么 C++ 不具备的语言特性。
    marding
        209
    marding  
       193 天前
    @ipwx 哈哈 回头试试
    1  2  3  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2647 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 05:00 · PVG 13:00 · LAX 22:00 · JFK 01:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.