首先,在瞭解block三大類型以前,咱們須要瞭解一個知識:c++
(舒適提醒:若是個人以前博客你沒有看,有些概念你不清楚的話,你可能很難理解,若是前面你都看了,這篇博客你看就像切菜同樣簡單!)程序員
一個由C/C++編譯的程序佔用的內存分爲如下幾個部分markdown
棧(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操做方式相似於數據結構中的棧。數據結構
堆(heap): 通常由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式相似於鏈表。iphone
全局區(靜態區static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域,程序結束後由系統釋放。函數
文字常量區:常量字符串放在這裏, 程序結束後由系統釋放測試
程序代碼區:存放函數體的二進制代碼。spa
相信你們對上面的這些內存分配的知識點都已經很是清楚,那咱們就看一下指針
接下來咱們就看看,block就是一個oc對象,那咱們就能夠按照oc的,直接調用class就知道它的類型了code
這裏能夠看出我前面說的,block就是oc對象,而這個NSGlobalBlock是繼承NSBlock的,其餘的種類都是繼承NSBlock,等說完了,你們能夠用這個方法試試其它2種block的的父類.
上面就是block的總共的三種類型:NSGlobalBlock、NSStackBlock、NSMallcBlock,
,這是運行時輸出的結果,其實編譯的結果可能有點不同,那咱們就把這份文件轉成c++文件,這個我以前的博客都提了不少次,此次我就不細說了(xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cpp)
其實你會發現,編譯之後生成的都是NSConcreteStackBlock類型,首先咱們確定以運行時爲準,由於編譯過程還有個運行,運行就會用runtime動態修改你的東西;還有其實用clang轉成c++的代碼,有時候並不必定就是最終的代碼,其實差異是不大,其實在llvm大概6.0之前都是同樣的,如今會生成一箇中間文件,還有就是程序運行中也是比較準確,若是有同窗查看源碼感受不同,不要很驚訝,這個很正常,能夠參考,差異不大.
咱們繼續看
而GlobalBlock是在數據區域,MallocBlock是在堆區,StackBlock是在棧區,我這裏不說堆、棧、數據區域的區別了,你們這個知識點若是不懂能夠去查閱一下它們的區別,否則後面的很難理解
先看個人總結,咱們再細細看
auto變量你們清楚吧?auto變量就是它所在的區域執行完畢,自動銷燬的變量.若是不知道請看我上一篇博客,介紹的很是清晰.接下來咱們就一個一個看每種類型的block
請看下面的代碼
訪問static的局部變量,全局變量a,都不是auto變量,因此上面3種狀況都是GlobalBlock,由於GlobalBlock咱們實際中用的很是少,因此這個也沒有過多的須要闡述的
按照咱們表格上面說的訪問了auto變量的block就是StackBlock,那我看一下下面的代碼:
ARC下運行的結果
應該有同窗注意,結果和咱們上面的結論不同,實際上是由於這環境是ARC,ARC下其實幫你作了不少事(這個爲何會這樣,這個內容仍是有點多,後面的博客,我會細說,你先無論這個爲何是這樣),因此咱們改爲MRC才能看到它的本質(直接把Objective-C Automatic Reference Counting 設置爲NO便可),咱們再看下面
MRC下運行的結果
這就是StackBlock類型,下面咱們再深刻看一下這個StackBlock一個特殊狀況,以下圖
MRC下運行的結果
注意到沒有,這個age的值變得很奇怪.這是由於:test()函數的做用域執行結束之後,它的做用域中的棧上面的變量就會銷燬,好比裏面的block就是StackBlock,全部test()執行完畢之後,block已經被釋放了,致使訪問內部就會出現混亂的狀況.整個block內存被釋放了裏面的全部都會出現混亂
答案很明顯,咱們把block棧內存變成堆內存就好了哇!怎麼變成堆block,是否是直接棧調用copy就能是堆block了,那咱們再試試:
是否是就很容易解決了!可能有同窗還有疑問,若是把GlobalBlock也來調用copy會是怎麼樣呢?這個你們能夠本身驗證,答案仍是:GlobalBlock,若是把MallocBlock也來調用copy會是怎麼樣呢?這個你們能夠本身驗證,答案仍是:引用計數加1
還有若是咱們block訪問一個對象,一個對象也是auto變量,因此也是同樣的,這些我就不驗證了,若有疑問能夠評論區討論.
這個上面已經說的很清楚了
相信還有同窗有疑問,剛剛咱們是MRC下測試的,至於ARC爲何會是另外一個結果,我後面的博客會說到!