c++ reference counting引用计数原理
?我們都知道,c++最令人頭疼的問題也是被其他語言鄙視的問題——指針管理。而引用技術(shù)能夠讓上面的簡化了不少。下面說說c++引用計(jì)數(shù)的設(shè)計(jì)原理。
? ? ? ? 引用計(jì)數(shù)的兩個(gè)動(dòng)機(jī):
? ? ? ? ? ? ? ? 1. 簡化heap對象周邊的記錄工作。對于分配在heap中得內(nèi)存,如果沒有顯式delete它,那么就會常駐在內(nèi)存區(qū)間,引起內(nèi)存浪費(fèi)。而且在heap對象的所有權(quán)會隨著復(fù)制和賦值出現(xiàn)轉(zhuǎn)移,所以編譯器還需要記錄對象的所有者是誰,這絕對是件吃力不討好的事情。有了引用計(jì)數(shù),對象使用該技術(shù),對象便擁有它自己。一旦不再有任何人使用它,它便自動(dòng)銷毀。這種技術(shù)最終構(gòu)建出了垃圾回收機(jī)制(多說一句,這種技術(shù)在游戲開發(fā)過程中一天都沒有用)。
? ? ? ? ? ? ? ? ?2.引用計(jì)數(shù)的最重要功能是對象共享。當(dāng)有許多對象有相同的值時(shí),將該值存儲多次是一件愚蠢的事。因此讓所有等值對象共享一份實(shí)值即可滿足要求,這樣既節(jié)省內(nèi)存空間,也讓速度加快(構(gòu)造、析構(gòu)對象費(fèi)時(shí))。
? ? ? ? ?雖然引用技術(shù)能夠帶來足夠的便利,但它也會產(chǎn)生一些令人難過的影響。舉個(gè)例子吧!
? ? ? ? ?假如有3個(gè)對象共享一個(gè)實(shí)值對象,即a、b、c都指向“hello ,world”字符串。現(xiàn)在我們想要修改a的值,注意這里只是需要修改a的值,而b、c的值不變,這時(shí)引用計(jì)數(shù)會讓你無所適從。一改都改,不改也不能達(dá)到目的。怎么辦?
? ? ? ? ?我們需要追蹤引用計(jì)數(shù)的對象有多少個(gè)對象共享它。如果有一個(gè)共享對象修改做出修改時(shí),我們不能改變引用計(jì)數(shù)對象,因?yàn)檫€有其他共享對象需要它。這是引用計(jì)數(shù)的數(shù)值開始派上用場了。這也是引用計(jì)數(shù)不得不添加的開銷。亦即我們需要存儲所共享的對象,也需要保存該對象的引用次數(shù),兩者是一個(gè)耦合關(guān)系。
? ? ? ? ? 引用技術(shù)的實(shí)現(xiàn)方式是采用一個(gè)數(shù)據(jù)結(jié)構(gòu),其中含有引用次數(shù)和實(shí)際的數(shù)據(jù)對象。該數(shù)據(jù)結(jié)構(gòu)將“某特定對象”以及“共享該對象的對象個(gè)數(shù)”關(guān)聯(lián)起來。但是引用計(jì)數(shù)有一個(gè)例外:分開構(gòu)造,但擁有相同初值的對象,不會共享該數(shù)據(jù)結(jié)構(gòu),因此各自的引用計(jì)數(shù)沒有關(guān)系。例如:
? ? ? ? ? string s1("hello world");
? ? ? ? ? string ?s2("hello world");
? ? ? ? ? s1和s2有著相同的string初值,由于其是分開構(gòu)造,所以不會共享數(shù)據(jù)結(jié)構(gòu),即其引用計(jì)數(shù)都為1.而下面的代碼:
? ? ? ? ? string s1("hello world");
? ? ? ? ? string s2 = s1;
? ? ? ? ? ?如果將s2賦值s1,那么兩者的構(gòu)造過程一致,此時(shí)共享數(shù)據(jù)結(jié)構(gòu),那么s2賦值會導(dǎo)致引用計(jì)數(shù)+1。
? ? ? ? ? ?當(dāng)然我們也可以實(shí)現(xiàn)只要是指向相同的對象就使用引用計(jì)數(shù)技術(shù),即僅僅在“面對真正獨(dú)一無二的字符串時(shí)”才產(chǎn)生新的對象,否則都共享原有的對象。不過這樣子代價(jià)太大,一般不提倡。
總結(jié)
以上是生活随笔為你收集整理的c++ reference counting引用计数原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 纯虚函数能为private吗?
- 下一篇: c++ 继承机制易犯的错误