之前写 TypeScript 时,习惯给能加 const 的变量都加上 const 。
但 C++ 里加上 const 后代码累赘了不少。
const auto v = .....
const char* const buf = ....
而且 STL 容器使用 const 修饰后,容器本身也不能修改了,而非只是变量不能改。
所以 C++ 里加上尽可能多的 const 是不是一个好风格?
要是有一个关键字能直接推导类型并定义成 const 就能更美观了。例如:
#define let const auto
1
macha 2023-09-18 18:23:31 +08:00
当然咯,只是很多人省事不加而已。
|
2
wevsty 2023-09-18 18:38:16 +08:00
能用 const 的地方尽量使用 const 是一个好习惯,因为能避免意外的修改。
对 STL 来说也是一样的,容器内部数据的变动很可能造成迭代器的失效或者多线程访问时出现各种各样的问题,如果确定一个地方不应该对容器内部数据进行修改,那么就应该鼓励传入 const 引用。 当然,实际操作上还是得看具体的代码需求就是了。 |
3
inhzus 2023-09-18 18:39:17 +08:00
大部分情况下、主流观点认为是是好风格(当然偶尔会看到一些也有道理的反驳观点)
|
4
weeei 2023-09-18 18:41:19 +08:00
只在关键的地方加也行,比如函数后面、局部指针变量,能够让编译器优化和避免一些低级错误。
|
5
LuckyPocketWatch 2023-09-18 18:42:57 +08:00
@inhzus
比如? |
6
xiangyuecn 2023-09-18 18:44:29 +08:00
支持禁用 const 关键字。
|
7
weeei 2023-09-18 18:48:52 +08:00
比较操蛋的应该是 const int *p, int * const p, const int * const p; 的理解。
|
8
Lightbright 2023-09-18 18:53:21 +08:00 via Android
@weeei 什么年代了还在用传统指针 (逃
|
9
agagega 2023-09-18 18:58:30 +08:00
指针的情况,类型开头那个 const (表示指向的内容不可修改)没问题,后面的 const (表示指针本身不可修改),多数时候用不上,写起来也麻烦。因为编译器是能知道你的指针有没有被重新赋值的,大多数时候你也不需要这个约束。
定义常量的话,用 const 当然也没问题,但 constexpr 可能更接近直观理解的那种「常量」。 给方法末尾加 const 是好习惯,否则 const 对象就无法访问这些方法了。 传参数的时候,传统意义上觉得写 const T&比较好,因为这样左值右值都能传,但如果你知道这个对象不是很大,直接按值传递 T 也是好的。 C++这个 const 明显比各种对象语义的语言更好理解(先不考虑 mutable 和 const_cast 的话),一旦 const 就是整个都不能修改。 |
10
weeei 2023-09-18 19:00:37 +08:00
@Lightbright 网上很多正确使用 unique_ptr 、shared_ptr 和 weak_ptr 的文章,想用好不容易啊
|
11
mainjzb 2023-09-18 19:00:51 +08:00 2
是。所以 rust 默认是 const 的,除非你显示的写明 mut 才可修改。当然 C++不能这么来,历史代码不允许这样的改动。
当然 C++还有 conprex ,能 conprex 的优先 conprex 情况变的更复杂(逃 dart 稍微好点用 final 关键字等价于 const auto |
12
leonshaw 2023-09-18 19:08:58 +08:00 via Android 1
应加尽加
|
13
LuckyPocketWatch 2023-09-18 19:41:33 +08:00
@Lightbright
去年接手过一段代码,是某个机床的输入设备的驱动代码,注释上的日期是 1982.06.。。。 |
14
yalay 2023-09-18 19:59:28 +08:00
flutter 就是各种 const ,当然对性能有好处的
|
15
cnbatch 2023-09-18 20:00:02 +08:00
喜欢加 const 那就加,无可厚非
虽然我个人不喜欢动不动就 const |
16
lovelylain 2023-09-18 20:20:52 +08:00 via Android
我一般只对必要的加 const ,例如函数参数列表或返回值里的 const 指针或引用,const 常量定义,const 成员方法,const 类型转换等。基本不会对值传递的参数加 const ,也很少用 const auto 去接收函数返回值,有时候会用 const auto&接收返回值。
|
17
nullyouraise 2023-09-18 22:58:40 +08:00
我是习惯先加,报错时再去掉
|
18
jaggerjiang 2023-09-18 23:09:27 +08:00
rust 默认就是 const
|
19
kneo 2023-09-18 23:14:06 +08:00 via Android
你要是确定能行就加。
就怕你自己稀里糊涂,今天加明天发现有代码编译不过去,还不知道得改哪儿。 |
20
tool2d 2023-09-18 23:50:05 +08:00 1
现代编译器那么聪明( clang ),我觉得他应该比我更懂 const ,所以我选择不加。
我以前也一直加,加到最后发现是给自己在设置编译障碍,干脆就不加了。 |
21
leimao 2023-09-18 23:52:42 +08:00
Best practice for const.
https://leimao.github.io/blog/Const-Pass-By-Value/ |
22
leimao 2023-09-18 23:56:13 +08:00
const is also very useful in many different applications in practice, in addition to the optimizations from the compiler:
https://leimao.github.io/blog/CPP-Const-Overloading/ https://leimao.github.io/blog/CPP-Const-Iterator/ |
23
leimao 2023-09-19 00:00:09 +08:00
Also do not abuse define in C++.
|
24
shaoyie 2023-09-19 00:21:35 +08:00
你把写代码看作是写文章,主要是你要表达的主义要丰富,合理,恰到好处
|
25
InvalidUsername 2023-09-19 00:32:00 +08:00 via Android
是的,「 Effective C++」中 条款 03 就是:尽可能使用 const
|
26
haohaolee 2023-09-19 01:18:01 +08:00
如果找不到理由不加 const ,那就加。搜索 const correctness
|
27
tyzandhr 2023-09-19 01:30:04 +08:00 via Android
谷歌风格指南里写,函数参数若不是传出值的指针,则必须写 const 。实际上我会尽可能用 constexpr 吧。
|
28
dangyuluo 2023-09-19 04:07:35 +08:00
@tool2d 相反,编译器又笨又保守(in a sense),没有你的指示,根本不敢做任何优化。所以正确地使用`const`才能让编译器变聪明
|
29
dangyuluo 2023-09-19 04:13:13 +08:00
比如在某个函数内,编译器无法保证其他进程不去改变`debug`这个 namespace scope 变量,就要傻傻地去生成 ASM 代码。加一条`bool debug_local = debug`就好了
```cpp for (int i = 0; i < n; i++) { ... if (debug) { // Global variable, can be possibly changed by printf printf("The data is NaN\n"); } } ``` |
30
nuk 2023-09-19 05:05:04 +08:00
不加,从来不加,C 本来就是需要修改各种变量的,除在形参以外的 const 毫无意义。
|
31
tool2d 2023-09-19 09:29:17 +08:00
|
32
Evovil 2023-09-19 09:48:17 +08:00
就是因为经常有人讨论,加 const 是不是最佳实践
才会出现 rust 这种完全不信任程序员的语言。。。 |
33
araraloren 2023-09-19 09:52:35 +08:00
@nuk c is not c++
|
34
yolee599 2023-09-19 09:55:25 +08:00
一些常量一般我都加 const ,比如查表法算 CRC 的表,接收到的指令和回调的映射表,字符串。还有函数参数只输入的,加 const 后就可以同时接收 const 和非 const 的变量,通用型更强。
|
35
hazardous 2023-09-19 10:30:03 +08:00
不但变量加 const ,成员函数我现在都能加 const 都加 const 了
|
36
dangyuluo 2023-09-19 10:46:43 +08:00
@tool2d `clang`在处理这个问题上是一样的,也是不敢贸然优化。不是 GCC 的锅。
这里用 volatile 是错的思路。具体就不详细展开了,这有一篇很好的文章。 https://liam.page/2018/01/18/volatile-in-C-and-Cpp/ |
37
dangyuluo 2023-09-19 10:48:42 +08:00
不过可以理解,关于 volatile 有太多错误的“讲解”了,很多人理解都有问题
|
38
dangyuluo 2023-09-19 10:55:30 +08:00 1
我突然想通你为什么说用 volatile 了,因为我们讨论的问题不是同一个。我指的是如果编译器能确定 loop 里的函数没有 side effect 后,可以执行 Loop unswitching 优化。Local const 变量可以做到这点
https://en.wikipedia.org/wiki/Loop_unswitching 你指的是如何用 volatile “禁止”编译器优化掉`if(debug)`,从而每次循环都去内存位置检查`debug`的 most-up-to-date 值 |
39
lakehylia 2023-09-19 11:07:10 +08:00
实际上,ide 会提示你加 const 更好。。。
|
40
lotem 2023-09-19 18:03:27 +08:00
能加 const 就加,是好的編碼習慣。卻不是好的風格。
好的風格是,像某些其他語言那樣,變量綁定默認不可變。 |
41
7B2fWg4Y9X 2023-09-20 11:36:35 +08:00
const 具有传染性,除此之外都是提示和你协作的程序员或者是你自己的一种方法。如果和我协作的人能够清晰的知道自己要做什么,我不会加;如果是我自己开发我也不会加,除了这两种情况之外我会加 const
|
42
Soora 2023-09-21 17:08:07 +08:00
是个好风格,好处:
1. 提升编译器优化空间, 可以看 csapp 第五章了解如何写出编译器友好的代码 2. 提高可读性 3. 防止意外修改 |