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

232 天前
 xiaotianhu
「现代化」的语言写多了,golang/swift ,还有各种怎么写都行的 PHP/JS

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

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

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

效率根本上不去啊
2221 次点击
所在节点    C++
21 条回复
zmcity
232 天前
建议用个好点的 IDE ,比如 Clion 或者 VS ,帮助提高编码效率。
如果觉得死记硬背语法太痛苦,学习一下编程语言的进化史,大概就能纠正编程习惯了。
zmcity
232 天前
熟悉了 C++的语法之后如果还想进一步提高 C++的编码能力,可以去学学 Rust 。
crayygy
232 天前
额... 这就是 C++ 的本来面貌,写多了 C++ 来看的话这反而是最直觉的
比如

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

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

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

不过也许可以考虑一下 Rust ?编译器教你写代码的感觉
zsxzy
232 天前
多年不写头文件保护宏.. 用 #pragma once 即可
ysc3839
232 天前
“记得写头文件保护宏”
主流编译器都支持 #pragma once

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

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

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

全自动 这个确实 C++ 不行, go 是自己只管写, goland 自动就 import 了, 同是 jb 家的, clion 需要写完后, an Alt+enter 才能导入,有时候还不能识别, 需要手写 include
xuhai951753
232 天前
我觉得 template 才是噩梦的开始
cnbatch
232 天前
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
232 天前
脚本语言写多了甚至会问自己有多久没写过析构了
jorneyr
232 天前
定义和实现分开是非常好的方式,暴露的是让调用者需要知道的内容,而不像 go ,Java 等该不该暴露的全暴露。
LitterGopher
232 天前
因为 C++ 面向的是计算机,而不是面相程序员。
agagega
228 天前
只有 class 要加分号这个是纯粹的语法噪音。

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

定义和声明要区分主要也是为了兼容早期的 C 编译器行为。你看一个 class 里面定义方法就不需要在乎前后关系。这些问题细究为什么其实会很有趣,推荐读一读《 C++语言的设计与演化》这本书。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/975208

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX