看板 C_and_CPP 關於我們 聯絡資訊
開發平台(Platform): (Ex: Win10, Linux, ...) Win10 問題 剛入門學習C++, C++ Primer, 5e, 2.4.3頂層的const小節提到: 「當我們拷貝一個物件,頂層const會被忽略。」 「另一方面,低層const永遠都不會被忽略。」 其中有個舉例: const int ci = 42; int &r = ci;//錯誤 1.「頂層const會被忽略、而低層就永遠不會」這個原則是從哪裡產生的呢? 為什麼不要一律保留const,而要區別頂層低層,並且有忽略跟保留的差異, 這是為了解決什麼問題嗎? 2.為什麼ci的頂層const沒有被忽略呢?如果照頂層const會被忽略的原則, 應該可以將普通int&繫結到const int物件上,為什麼不行呢? 是因為參考並沒有涉及拷貝的動作,單純只是給另一個變數加上別名而已, 所以就沒有忽略頂層const這件事嗎? 請板上的大師們不吝教導,看了好幾篇文章還是不理解為什麼要有這種機制... -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.251.33.237 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1624127378.A.D92.html ※ 編輯: museangel (111.251.33.237 臺灣), 06/20/2021 02:41:52
nh60211as: 你那不是拷貝物件,是取得物件的reference 06/20 02:39
museangel: 對耶 真的忽略這件事...@@ 06/20 02:43
museangel: 另外為什麼要有區分頂層跟低層的機制呢 怎麼不都保留呢 06/20 02:44
LPH66: 這裡應該是指一個指標本身的常數性和指標指向值的常數性 06/20 03:06
LPH66: 常數性這種事是綁在變數上的, 只要有一個方式參照變數 06/20 03:06
LPH66: 那就能談論這個參照存取的常數性 (不可變性) 06/20 03:06
LPH66: 但當我們 assign 值出來時, 我們是複製值 06/20 03:07
LPH66: 因此這最頂層變數參照被我們解參照了, 其常數性不再有意義 06/20 03:08
LPH66: 因此講忽略有點簡略, 因為會忽略的原因是解參照取值了 06/20 03:09
LPH66: 在這個例子裡, int& 這是一個 C++ 參照, 參照一個變數 06/20 03:10
LPH66: 所參照的變數是 ci, 這裡是參照指定並沒有解參照取值 06/20 03:11
LPH66: 所以就算是頂層的常數性依然會保留 06/20 03:11
抱歉還是沒辦法理解, 假如: const int i = 1; const int *const j = &i; const int *const k = j; 「但當我們 assign 值出來時, 我們是複製值」 k複製j的值,也就是取得j的記憶體存放的i位址。 「因此這最頂層變數參照被我們解參照了, 其常數性不再有意義」 請問j是在指派給*const k時被解參照嗎? 不太懂什麼時候最頂層變數被解參照… 我可以理解成: 「只要A變數被指派給B變數,就是僅僅傳遞A的值給B,不會傳遞其餘存在A變數上的特性, 而在B變數上,施加在A變數的種種特性都不會存在」嗎? 不過這又回到了為什麼A變數的種種特性都不會在B變數上面存在的問題了...
g0010726: 用個比喻來形容好了, 一個不能被塗改的書像是圖書館內 06/20 04:08
g0010726: 的書(const Book), 你在copy後得到的新書究竟能不能被 06/20 04:08
g0010726: 塗改你可以自己決定,跟原本的書沒關係。但如果你有個 06/20 04:08
g0010726: reference或pointer代表著(指向)圖書館的書,這個狀況 06/20 04:08
g0010726: 下const就該被保留,因為那本圖書館的書不該被塗改 06/20 04:08
沒辦法理解copy之後為什麼原本變數的一部分特性就消失... ※ 編輯: museangel (111.251.33.237 臺灣), 06/20/2021 08:10:55
sarafciel: const不是變數與生俱來的特性 const是一種契約 06/20 08:59
sarafciel: 關於"某個特定位置上的某個值,我不會去改他"的契約 06/20 09:03
sarafciel: 然後參考不是別名 參考是一種拷貝 只是他copy的東西是 06/20 09:17
sarafciel: 位置 參考實際上是封裝後的指標 而不是別名 06/20 09:18
sarafciel: 你把問題想得太複雜了 實際上只是有沒有可能改到那個ci 06/20 09:22
sarafciel: 的值 所以這份契約要不要延續的問題 06/20 09:23
謝謝各位大師從各種不同角度說明,很開心終於理解了! 確實常數就是要限制特定變數的記憶體內的值不要被更動而已, 如果複製出去各自分離、互不干涉的,就不需要為新分出去的值加上不能更動的限制。 原本一直糾結在什麼頂層const、低層const, 沒有意識到,只要結合設定常數的目的:「不讓特定變數記憶體內的值更動」, 跟指派「是拷貝原本變數記憶體內的值」, 而由「拷貝出的值有無可能影響到常數變數記憶體內的值」,再去想就通了。 一、在基礎型別的指派中: 每個變數的記憶體位址裡面存有各自的值, 而const就是要保護被它套用的特定變數的記憶體位址內的值不被更改, 在拷貝過後,已經各自分離, 故新變數內的值無論怎麼更動都不會影響到常數變數記憶體內存放的值, 不用在新變數套上const。 二、在複合型別的指派中: 1.指向常數基礎型別的常數或非常數指標: 如前述,因為拷貝後各自分離, 可不在意此處是否為常數指標,只要關注被指向的基礎型別變數是否為常數, 而之所以還需要關注,是因為指標內存放的位址, 存有常數基礎型別變數被限制不能更動的值,非其他被複製出去已各自獨立的值。 2.參考常數基礎型別的常數參考: 因為參考會更動到基礎型別的記憶體內存放的值,(雖然不知道參考是怎麼封裝的指標...) 因此在被參考之物件為常數基礎型別時,就必須讓參考同樣是常數參考, 否則就會有可能更動到常數基礎型別變數的記憶體內所存放的值。 ※ 編輯: museangel (111.251.33.237 臺灣), 06/20/2021 11:50:54
howareuuu: 推比喻 06/21 08:24