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