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

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

  •  
  •   xiaotianhu · 2023-09-19 15:24:59 +08:00 · 2551 次点击
    这是一个创建于 429 天前的主题,其中的信息可能已经有所发展或是发生改变。
    「现代化」的语言写多了,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  
       261 天前
    @InkStone "C++最可怕的地方是三种语义"
    哪三个?
    nooneanyone
        22
    nooneanyone  
       188 天前
    这不就是语法么,你写模板编程还得一边写一边在脑子里编译呢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1511 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:59 · PVG 07:59 · LAX 15:59 · JFK 18:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.