C++反直觉的地方好多,好痛苦 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaotianhu
V2EX    C++

C++反直觉的地方好多,好痛苦

  •  
  •   xiaotianhu 2023-09-19 15:24:59 +08:00 3124 次点击
    这是一个创建于 821 天前的主题,其中的信息可能已经有所发展或是发生改变。
    「现代化」的语言写多了,golang/swift ,还有各种怎么写都行的 PHP/JS

    然后发下,c++反直觉的地方太多了,想哭

    - 要记得 include 头文件,包括语言级的 STL 的各种功能
    - class 的声明要加分号;
    - 记得写头文件保护宏
    - 奇怪的构造函数和析构函数定义
    - 区分「定义」和「声明」
    - 记得加 const ,并区分引用和指针

    编码十分钟,纠正习惯半小时...然后对着各种奇怪的报错改代码

    效率根本上不去啊
    22 条回复    2024-05-17 19:50:01 +08:00
    zmcity
        1
    zmcity  
       2023-09-19 15:42:27 +08:00
    建议用个好点的 IDE ,比如 Clion 或者 VS ,帮助提高编码效率。
    如果觉得死记硬背语法太痛苦,学习一下编程语言的进化史,大概就能纠正编程习惯了。
    zmcity
        2
    zmcity  
       2023-09-19 15:43:34 +08:00
    熟悉了 C++的语法之后如果还想进一步提高 C++的编码能力,可以去学学 Rust 。
    crayygy
        3
    crayygy  
       2023-09-19 15:47:45 +08:00
    额... 这就是 C++ 的本来面貌,写多了 C++ 来看的话这反而是最直觉的
    比如

    - 要记得 include 头文件,包括语言级的 STL 的各种功能

    没有用到的功能不需要 include ,要用的才会被引用进来

    只能说现代语言都太省事儿了,把很多事情都默默处理好了,让开发能省心很多 ;-)

    不过也许可以考虑一下 Rust ?编译器教你写代码的感觉
    zsxzy
        4
    zsxzy  
       2023-09-19 15:49:52 +08:00
    多年不写头文件保护宏.. 用 #pragma once 即可
    ysc3839
        5
    ysc3839  
       2023-09-19 15:52:59 +08:00 via Android
    “记得写头文件保护宏”
    主流编译器都支持 #pragma once

    “区分「定义」和「声明」”
    全写到一个文件里,然后一个 cpp include 即可,虽然这么做会拖慢编译速度,但后续可以快速升级成 C++ module ,module 是支持分开编译的,就不会拖慢速度了。
    squarefong17
        6
    squarefong17  
       2023-09-19 15:53:26 +08:00
    大学第一门学的就是 C 艹。。。后来学 js 的时候觉得十分反人,什么鬼类型系统,想深拷贝怎么那么难( Doge
    xtreme1
        7
    xtreme1  
       2023-09-19 15:59:12 +08:00
    合理使用现代 c++, 完全可以写得和你举例的所谓「现代化」的语言差不多甜...
    虽然这一点也可以拿来吐槽...
    bruce0
        8
    bruce0  
       2023-09-19 15:59:49 +08:00
    include 这个没啥槽点吧 go Java Python 这些也一样要 import 吧
    InkStone
        9
    InkStone  
       2023-09-19 16:01:12 +08:00
    你说的这些都太 trivial 了……还完全不涉及 C++限额的一面呢。。。

    C++最可怕的地方是三种语义、五种构造函数带来的深不见底的隐式代码
    stinkytofu
        10
    stinkytofu  
       2023-09-19 16:02:54 +08:00
    @bruce0 #8 主要 java 这种现代 IDE 可以自动 import, C++用 CLion 的话好像没有这么智能
    xiaotianhu
        11
    xiaotianhu  
    OP
       2023-09-19 16:05:26 +08:00
    @bruce0 #8 基本上全自动,减少了很多记忆成本啊。
    tool2d
        12
    tool2d  
       2023-09-19 16:05:29 +08:00
    如果一个人说他 C++开发效率超高,那我严重怀疑,他是不是真的在写 C++

    一般来说,C++这种偏底层语言,调试时间是远大于写代码时间的。
    xuelang
        13
    xuelang  
       2023-09-19 16:07:40 +08:00
    不说对新手了,写了很久的人也会被搞得很懵,比如:
    深入理解 C++ 链接符号决议:从符号重定义说起
    https://selfboot.cn/2023/09/19/c++_symbol_resolution/
    bruce0
        14
    bruce0  
       2023-09-19 16:08:43 +08:00
    @stinkytofu
    @xiaotianhu

    全自动 这个确实 C++ 不行, go 是自己只管写, goland 自动就 import 了, 同是 jb 家的, clion 需要写完后, an Alt+enter 才能导入,有时候还不能识别, 需要手写 include
    xuhai951753
        15
    xuhai951753  
       2023-09-19 16:09:24 +08:00   1
    我觉得 template 才是噩梦的开始
    cnbatch
        16
    cnbatch  
       2023-09-19 16:12:52 +08:00
    O 是否 P 从未碰过 C 系列语言?如果是,那么这不是反直觉,而是与你习惯不同

    先说 include 头文件,虽然办法是古早了点(来自于 C 语言),但换成其他语言也得 using 、import 呀,哪怕是语言内置的同样都要导入,比如 C# 的 List<T>(位于 System.Collections.Generic )、Java 的 List<E>(位于 java.util ),尽管大多数时候 IDE 已经帮忙写了导入语句,但不代表不需要导入

    class 声明需要加分号,很简单,因为 C++的 class 就是基于 struct 的。

    不想用头文件的话,可以试试 C++20 开始支持的 modules 特性(模块),虽然支持的编译器并不够广泛。

    构造函数和析构函数……OP 果真没接触过 C# 和 Java 吗?构造函数同样存在于 C# 和 Java 当中,这没什么好奇怪的吧。顶多就是 C++的构造函数种类比较多。
    至于析构函数,C# 甚至有两个呢(一个~开头,跟 C++ 一样;还有一个是 Dispose ),同时还存在于许多语言当中,不明白这有什么好奇怪的。

    区分定义和声明,好处体现在需要隐藏细节的时候,例如需要发布闭源 SDK 的话,这个特点很有用,只需要把头文件和二进制包分发出去就行了,不用把完整源码交给对方。
    当然啦,实际上完全可以全都写在头文件内的,Github 有许多 header-only 的库就是这么干的。

    const 的话题,昨天刚好有人提到: /t/974941
    这个可以进去谈一谈

    区分引用和指针其实很方便呀,一来可以避免出现多级指针的次数,二来配合模板可以原样转发入参。
    我个人是尽量使用引用
    ztxcccc
        17
    ztxcccc  
       2023-09-19 16:33:32 +08:00
    脚本语言写多了甚至会问自己有多久没写过析构了
    jorneyr
        18
    jorneyr  
       2023-09-19 16:35:41 +08:00
    定义和实现分开是非常好的方式,暴露的是让调用者需要知道的内容,而不像 go ,Java 等该不该暴露的全暴露。
    LitterGopher
        19
    LitterGopher  
       2023-09-19 16:37:56 +08:00
    因为 C++ 面向的是计算机,而不是面相程序员。
    agagega
        20
    agagega  
       2023-09-24 01:03:30 +08:00
    只有 class 要加分号这个是纯粹的语法噪音。

    头文件这个编译模型你可以说它不现代,拖慢编译速度,但要说反直觉,其他语言的模块化系统对初学者也没有顺直觉到哪里去。也许 Swift 的比较无脑,但代价就是复杂度都被隐藏到构建系统里去了。最早学 C 的时候,不清楚链接究竟如何进行的,那时候以为拆分 C 文件的目的纯粹是好看,大项目最终会把所有源文件都 include 到一个大的.c 里进行编译。而因为 include 是非常无脑的操作,所以才要写头文件保护宏,Objective-C 支持#import 来保证只 include 一次,而很多编译器也提供了#pragma once 扩展。

    定义和声明要区分主要也是为了兼容早期的 C 编译器行为。你看一个 class 里面定义方法就不需要在乎前后关系。这些问题细究为什么其实会很有趣,推荐读一读《 C++语言的设计与演化》这本书。
    slideclick
        21
    slideclick  
       2024-03-05 09:18:49 +08:00
    @InkStone "C++最可怕的地方是三种语义"
    哪三个?
    nooneanyone
        22
    nooneanyone  
       2024-05-17 19:50:01 +08:00
    这不就是语法么,你写模板编程还得一边写一边在脑子里编译呢
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5192 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 08:41 PVG 16:41 LAX 00:41 JFK 03:41
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86