作者LPH66 (IS YOU)
看板C_and_CPP
標題Re: [問題] const 變數在.h, undefined behavior?
時間Thu Jul 25 18:21:11 2019
我回文整理一下好了, 推文好像會越推越長
※ 引述《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不是很正常嗎?
1F:推 LPH66: 執行兩次 ctor 正是他的第三點在說的07/25 17:44
2F:→ LPH66: 你以為只有一個全域變數其實有兩個07/25 17:45
3F:→ LPH66: 其證據即是建構子被執行了兩次07/25 17:45
4F:→ LPH66: 那在同一支程式裡有兩個同名字的不同全域變數即是 UB 了 07/25 17:48
5F:→ 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嗎
: 謝謝
6F:→ LPH66: 後半篇文章的 inline (C++17) 和 extern (pre-C++17)07/25 17:50
7F:→ LPH66: 它們的作用並不一樣: "It looks somewhat similar to07/25 17:51
8F:→ 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 了)
--
有人喜歡邊
玩遊戲邊
上逼;
也有人喜歡邊
聽歌邊
打字。
但是,我有個請求,
選字的時候請
專心好嗎?
-- 改編自「古 火田 任三郎」之開場白
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 180.177.3.123 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_and_CPP/M.1564050073.A.CDC.html
9F:推 kyushu: 推 07/25 18:49
10F:推 lovejomi: 所以好像是不是ub也不明確,但我們常常在cpp 寫一些cons 07/26 11:43
11F:推 lovejomi: 在global, 只要兩個cpp都不小心這樣寫撞名 難道就ub?這 07/26 12:02
12F:→ lovejomi: 樣要怎麼寫code... 07/26 12:02
13F:推 sarafciel: 1.你可以寫個singleton統一管理全域物件 07/26 17:39
14F:→ sarafciel: 2.不喜歡singleton,還可以拿個namespace包起來防撞名 07/26 17:40
15F:→ sarafciel: 3.你其實沒那麼需要讓大家都爽爽看的全域變數,不是貪 07/26 17:43
16F:→ sarafciel: 圖方便,就是對scope跟權責的控制沒有觀念 07/26 17:45
17F:推 sarafciel: 如果是後者,比起研究那些是UB然後不要踩雷,花時間去 07/26 17:52
18F:→ sarafciel: 學這些設計原則才是真的 07/26 17:53
19F:推 lovejomi: 可是你明明知道 const int 是internal linkage 你不該會 07/27 09:49
20F:→ lovejomi: 想擺在無名namespace吧? 多多少少寫cpp會想named magic 07/27 09:49
21F:→ lovejomi: number in global啊 撇除constexpr 07/27 09:49
其實說到 linkage
我在想會不會這種習慣/誤解有可能是因為在 C 語言這個是 external linkage 有關
同樣引用你舉過的那個地方:
> ... This is different from C where const file scope variables have external
> linkage.
在 C 的時代已經這樣理解/這樣被教導所以到了 C++ 照樣帶了進來這樣
不說別的, 我自己在仔細找過資料之前也有差不多的誤解...
※ 編輯: LPH66 (180.177.3.123 臺灣), 07/27/2019 12:49:42