Re: [问题] const 变量在.h, undefined behavior?

楼主: LPH66 (-6.2598534e+18f)   2019-07-25 18:21:11
我回文整理一下好了, 推文好像会越推越长
※ 引述《lovejomi (JOMI)》之铭言:
: https://www.fluentcpp.com/2019/07/23/how-to-define-a-global-constant-in-cpp/
: 偶然看到这篇,我其实觉得他写错
: 这部分
: Each file has its own version of焏. This is a problem for three reasons:
: it is undefined behaviour (objects must be defined only once in C++),
: ??????真的undefined吗?有没有什么表格或网址整理ub...之前看到说把东西写在
: namespace std也是ub...也太多很容易就写出来的ub了吧
一个很令人沮丧的事实是 C++ 确实很多很容易写出来的 UB...
: it uses more memory,
: if the constructor (or destructor) of曱温as side effects, they will be execute
: d twice.
: 这句看不懂,什么是side effect在这里?
: 他的范例我唯一能看出问题的就是你没办法保证cout比他的x先初始化
: 其他他说执行两次cstor不是很正常吗?
推 LPH66: 执行两次 ctor 正是他的第三点在说的07/25 17:44
→ LPH66: 你以为只有一个全域变量其实有两个07/25 17:45
→ LPH66: 其证据即是建构子被执行了两次07/25 17:45
→ LPH66: 那在同一支程式里有两个同名字的不同全域变量即是 UB 了 07/25 17:48
→ LPH66: 这是明确违反 one-definition rule 的 UB07/25 17:49
One Definition Rule (ODR) 是 C++ 里的一个很重要的概念
重要到标准里有一个衍生词叫做 "odr-used" 来形容一个东西
被如此形容的东西在整支程式的所有转译单元当中有且仅能有恰好一个定义
: 我只记得const自带static,所以默认是internal linkage
: https://en.cppreference.com/w/cpp/language/cv
: 的Note也是这样写
: 但他说是ub 我觉得很奇怪…..
不过下面的回应好像有跟你一样的问题:
qsvui ‧ 2 days ago
I'm not sure that your very first example of putting a const variable in the
header is undefined behavior.
他举了跟你提到的同样的段落表示怪怪的
: 最后他提到inline,
: inline跟extern效果一样,意思是c++鼓励使用inline而不是extern吗
: 谢谢
→ LPH66: 后半篇文章的 inline (C++17) 和 extern (pre-C++17)07/25 17:50
→ LPH66: 它们的作用并不一样: "It looks somewhat similar to07/25 17:51
→ LPH66: inline, but its effect is very different."07/25 17:51
文中很明确的跟你说了:
With extern, the above code is a declaration, and not a definition. With
inline, it was a definition.
extern 只做宣告不做定义, 所以可以在各个不同转译单元当中同时存在
但是若它被 odr-used 那你就必须给它一个定义
因此你必须在其中一个转译单元中定义它
C++17 的 inline 变量跟以前的 inline 函数的概念颇像 (或者该说就是这样延伸来的)
它能够有多于一个定义, 只要大家的定义完全相同即可
所以在 C++17 我们可以像贴 inline 函数一样为全域变量贴 inline
编译器就知道这些在各个转译单元中宣告 inline 的变量是同一个东西而把它整合在一起
而由于这已经是个定义, 因此就无须特别在其中一个转译单元中定义之了
(反而这里再多定义就违反 inline 的完全相同的约定, 那这就又是 UB 了)
楼主: LPH66 (-6.2598534e+18f)   2018-07-25 17:44:00
执行两次 ctor 正是他的第三点在说的你以为只有一个全域变量其实有两个其证据即是建构子被执行了两次那在同一支程式里有两个同名字的不同全域变量即是 UB 了这是明确违反 one-definition rule 的 UB后半篇文章的 inline (C++17) 和 extern (pre-C++17)它们的作用并不一样: "It looks somewhat similar toinline, but its effect is very different."
作者: kyushu (苏打绿吓倒我了)   2019-07-25 18:49:00
作者: lovejomi (JOMI)   2019-07-26 11:43:00
所以好像是不是ub也不明确,但我们常常在cpp 写一些cons在global, 只要两个cpp都不小心这样写撞名 难道就ub?这样要怎么写code...
作者: sarafciel (Cattuz)   2019-07-26 17:39:00
1.你可以写个singleton统一管理全域物件2.不喜欢singleton,还可以拿个namespace包起来防撞名3.你其实没那么需要让大家都爽爽看的全域变量,不是贪图方便,就是对scope跟权责的控制没有观念如果是后者,比起研究那些是UB然后不要踩雷,花时间去学这些设计原则才是真的
作者: lovejomi (JOMI)   2019-07-27 09:49:00
可是你明明知道 const int 是internal linkage 你不该会想摆在无名namespace吧? 多多少少写cpp会想named magicnumber in global啊 撇除constexpr

Links booklink

Contact Us: admin [ a t ] ucptt.com