Re: [問題] initializer 的具體作用

看板C_and_CPP (C/C++)作者 (髮箍)時間5年前 (2020/05/02 20:11), 5年前編輯推噓0(000)
留言0則, 0人參與, 最新討論串2/2 (看更多)
※ 引述《justhere (發廢文就是生活的小確幸)》之銘言: : 各位好,小弟新手, : 目前在看C++ primier fifth edition, : 進度到variable的定義與宣告這個小節, : 在講extern 這個keyword時書中舉一個小範例: : extern int i; // declares but does not define i : int j; // declares and defines i : 他解釋 : To obtain a declaration that is not also a definition, : we add extern keyword and may not provide an explicit initializer : 請問具體來說c++中initializer所做的事情是什麼呢? : 是分配記憶體位置和值給該name嗎? : 感謝 先不管 extern, 在語法上 int i; 這樣寫就是宣告. 而對於非函式 的宣告來說, 即使我們可以不寫 initializer, 但物件一定得經過 初始化, 而依照這個物件被宣告的地方, 會有不同的初始化行為, 有 static storage 如全域 int 物件, 就會經過 zero-initializ- ation (效果等同於 = 0, 和 memset(&obj, 0, sizeof(obj)) 意義 不同), 如果是區域 int 物件則不給初始值; 但無論給不給初始值, 物件被宣告的當下, 它的實體即存在於該 TU (translation unit) (這個結果才是書中說的定義) 在宣告前方加上 extern 修飾符語意就變了, 這時不為了創造物件 實體, 而是想在當下能重複使用某處宣告過的物件 (可以存在同個 TU 或別的 TU), 而跨 TU 存取的情況下, 這個物件必須要具備 external linkage 才行. 考慮以下程式碼, 請問印出的 i 值是多 少? // translation unit #1 static int i = 1; namespace ns { int i = 2; } // translation unit #2 void foo() { extern int i; // declare i but i is not defined in foo() std::cout << "i = " << i << std::endl; } 以上是陷阱題, 在 TU #2 裡面雖然預期會有個 i 宣告在全域底下 , 結果因為在 TU #1 裡全域的 i 宣告有加上 static 修飾符所以 無法在別的 TU 裡使用. 這段程式碼會造成連結錯誤. 加了 extern 的宣告還是有辦法回復原本宣告的功能, 只要明確地 用 initializer 初始化即可; 但是這樣寫語意是矛盾的, 通常編譯 器會給警告 (這時候會忽略 extern 修飾符). 除了函式會特別把宣告還有建立實體分成兩種寫法, non-inline static data member 也是如此: class foo { static int i; // declare here }; int foo::i = 1; // define here 這時候我們不會說 static int i; 是定義: 它還是宣告, 但真正建 立實體的動作必須從 class definition 拉出來寫在命名空間內. 最後來總結幾個重點: 1. 宣告或定義要看情境, 不是單純用語法來分辨 2. 加 extern 修飾符也可定義物件 3. extern 是用來存取具有 external linkage 的物件 (跨 TU) -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.193.76.216 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1588421464.A.70F.html ※ 編輯: loveme00835 (123.193.76.216 臺灣), 05/03/2020 00:44:31
文章代碼(AID): #1UhMDOSF (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1UhMDOSF (C_and_CPP)