作者lovejomi (JOMI)
看板C_and_CPP
标题Re: [讨论] 对於同事的coding style感到很感冒
时间Wed May 13 16:10:29 2020
谢谢各位的意见
我会在逐一理解
目前有几个问题
最近比较被要求写exceptional 的code
假设我写
string Foo(string s) noexcept
{
auto a = Get(); // noexcept
string r = s+a;
return r;
}
然後我确认operator+是不是noexcept
结果当然不是
变成我要为了这简单的+
写一个try catch...去handle exception
三个抉择点
1. 不要标注noexcept , 反正坏了上面该处理 无责声明 (我prefer这)
2. try catch(type1) catch(type2) catch(...) 把所有查的到的exception都handle
要不要分开handle 是by design
3. 就现在这样写 反正真的发生bad_alloc 我也无能为力 terminate吧
以上有没有什麽比较建议的做法可以讨用在多数情形
现在变成想提供noexcept 函数 都要查每一行function call是否都是noexcept
反而觉得 预设不该noexcept 才合理 有需求才标注noexcept
==================
一个很无聊的const问题
古早的effective c++推广 能加const就加
所以这位同事当然遵守
void Foo(const int a)
{
auto const rc = Win32();
auto const hr = COM();
auto const error = 3rdAPI();
...
}
我认同const能确保不被乱改
但我其实是觉得很多余
local变数改了也不会怎样(也不该怎样)
甚至会被改表示你有需求 搞不好还会因此改code拿掉const
问题来了
他今天看到某同事
void Bar(const string s){// read-only }
留言 这是多余的 要拿掉
对我来说当然不该补const 里面如果以後有copy需求 就不能move了
但我反倒觉得他两套标准
这case只有read加上const不正是他遵守的铁则吗?
也可以Bar(RVALUE); 为啥这情况他认为"useless"? 双重标准的感觉
我没看到他针对函数local non-trivial变数的写法
也许也是不加const为主 (也是双标)
这边的问题就是
尽可能const 这件事如果套用在modern C++ 有没有什麽common的标准用法呢?
我比较主观的归纳是
primitive type能const就const
non-trivial type 都不要加(但这太偏颇了)
我自己是习惯都不加
以上
谢谢
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.192.134.52 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1589357431.A.89A.html
※ 编辑: lovejomi (123.192.134.52 台湾), 05/13/2020 16:22:23
1F:→ poyenc: const 不是为了避免修改, 而是要求物件的行为 consistent 05/13 17:07
2F:→ poyenc: 这是为什麽 mutable 存在的原因, 这可以从两个角度来看: 05/13 17:10
3F:→ poyenc: 1) 给物件的人 2) 收物件的人, 对於收的人来说加上 const 05/13 17:14
4F:→ poyenc: 是希望物件的外显行为能一致, 这是基本假设. 对给的人来说 05/13 17:15
5F:→ poyenc: 加上 const 是用来限缩可用介面, 也许是为了避免状态被改 05/13 17:17
6F:→ poyenc: 动, 或者只是想提供不同的介面组合给对方 (使用 ref 05/13 17:21
7F:→ poyenc: qualifier 也可以达成类似目的). 所以收的时候需要注意绑 05/13 17:23
8F:→ poyenc: 定的 value category 以及 constness, 给的人也要看情况使 05/13 17:23
9F:→ poyenc: 用 std::forward()/std::move()/std::as_const() 05/13 17:24
10F:→ poyenc: 所以 pass by value 的情况下不用加上 const 的原因是使 05/13 17:30
11F:→ poyenc: 用者只有执行函式的执行绪, 所以要求行为一致是没有意义的 05/13 17:31
12F:→ poyenc: noexcept 的用意和 throw() 不一样, 在 C++ 里我们应该预 05/13 17:57
13F:→ poyenc: 设所有函式都会 throw 但你可以透过 throw() 来说你其实不 05/13 17:58
14F:→ poyenc: 会 throw, 而编译器所做的相应处理是把 propagate excepti 05/13 17:59
15F:→ poyenc: on 的 code 拿掉, 换句话说 noexcept 是优化的手段和 05/13 18:00
16F:→ poyenc: exception handling 策略无关, 那取舍其实就看团队了, 大 05/13 18:01
17F:→ poyenc: 部分针对 scalar type 的操作比较容易加上 noexcept 来优 05/13 18:01
18F:→ poyenc: 化, 而其他情形就看你们对效能的要求来做决定. 这都是需要 05/13 18:02
19F:→ poyenc: 先做 profiling 05/13 18:03
20F:→ lovejomi: 上面我需要理解一下,如果是primitive 加上const是必要 05/13 18:09
21F:→ lovejomi: 的吗? 05/13 18:09
22F:→ poyenc: 跟是不是 primitive 无关, 由预期的行为决定加不加 const 05/13 18:19
23F:→ poyenc: 如果你期望两次 std::cout << i << std::endl; 出来的值都 05/13 18:20
24F:→ lovejomi: 把 propagate exception 的 code 拿掉 <== 我想确认 05/13 18:20
25F:→ lovejomi: 内部使用try catch(...){} 确保他不会propagate 这件事 05/13 18:20
26F:→ lovejomi: 应该跟"compiler拿掉" 两者没冲突对吧? 05/13 18:20
27F:→ poyenc: 要一样, 不应该有其他执行绪去更改值, 最好加上 const 来 05/13 18:20
28F:→ poyenc: 表达意图 05/13 18:21
29F:→ poyenc: 没错, 但 noexcept 与否应该藉由实作程式码来决定而不是反 05/13 18:26
30F:→ poyenc: 过来由介面限制实作, 你在里面写了 try-catch 其实是和编 05/13 18:26
31F:→ poyenc: 译器做类似的事情, 所以我们才会用 noexcept() 运算子来决 05/13 18:27
32F:→ poyenc: 定函式的 signature 而不是用人工去比对 05/13 18:28
33F:推 FRAXIS: 那 class member 要加 const 吗? 如果初始化之後就不变了 05/13 21:29
34F:→ lovejomi: @poyenc: 问一下,你有这样深入见解是有读什麽文章或书 05/13 21:53
35F:→ lovejomi: 籍吗 05/13 21:53
36F:→ lovejomi: 我也从网路上找不少文章但没有这麽深入 05/13 22:01
37F:→ lovejomi: 另外 以我的范例 你会怎麽抉择实作 谢谢 05/13 22:02
38F:→ poyenc: @FRAXIS 要看你对该 instance variable 型别有什麽要求, 05/13 22:05
39F:→ poyenc: 在介面受限的情况下是不是还能实作你想要的类别, 来去决定 05/13 22:06
40F:→ poyenc: constness, @lovejomi 只是比较常和 committee member 讨 05/13 22:07
41F:→ poyenc: 论而已, 我觉得要看你对 const 的理解是到语法层还是语意 05/13 22:08
42F:→ poyenc: 层, 我的习惯是预设全加 const, 还有需要 noexcept 的情况 05/13 22:10
43F:→ poyenc: 全用 noexcept(bool) 来决定. 预设全加 const 是为了减轻 05/13 22:11
44F:→ poyenc: 读码的负担还有方便验证, 不过 pass by value 不会加const 05/13 22:12
45F:→ poyenc: 因为这情况在介面加 const 是多余的 05/13 22:13
46F:推 eye5002003: 至今没写过一次noexcept,这东西以後被删除的机率很高 05/14 09:05
47F:→ eye5002003: 我常常写foo(const std::string &str);既然read only 05/14 09:08
48F:→ eye5002003: 就没必要整个复制一遍了 05/14 09:10
49F:→ Jockey66666: 如果是string的话直接用string_view吧 05/14 22:38