一.了解clang
- Clang是?個C語?、C++、Objective-C語?的輕量級編譯器。源代碼發(fā)布于BSD協(xié)議下。
Clang將?持其普通lambda表達式、返回類型的簡化處理以及更好的處
理constexpr關鍵字 - Clang是?個由Apple主導編寫,基于LLVM的C/C++/Objective-C編譯器
- 2013年4?,Clang已經(jīng)全??持C++11標準,并開始實現(xiàn)C++1y特性(也就是C++14,這是
C++的下?個?更新版本)。Clang將?持其普通lambda表達式、返回類型的簡化處理以及更
好的處理constexpr關鍵字。 [2]
Clang是?個C++編寫、基于LLVM、發(fā)布于LLVM BSD許可證下的C/C++/Objective-C/
Objective-C++編譯器。它與GNU C語?規(guī)范?乎完全兼容(當然,也有部分不兼容的內(nèi)容,
包括編譯命令選項也會有點差異),并在此基礎上增加了額外的語法特性,?如C函數(shù)重載
(通過attribute((overloadable))來修飾函數(shù)),其?標(之?)就是超越GCC
二.編譯oc文件為c++文件
- 1.直接命令行編譯
clang -rewrite-objc main.m -o main.cpp 把?標?件編譯成c+
+?件
- 2.如果有系統(tǒng)庫會報錯 如:(UIKit報錯問題)
clang -rewrite-objc -fobjc-arc -fobjc-runtime=ios-13.0.0 -isysroot /
Applications/Xcode.app/Contents/Developer/Platforms/
iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator13.0.sdk main.m
- 3.用xcode 編譯(
xcode安裝的時候順帶安裝了xcrun命令,xcrun命令在clang的基礎上進?了
?些封裝,要更好??些)
xcrun -sdk iphonesimulator clang -arch arm64 -rewrite-
objc main.m -o
main-arm64.cpp (模擬器)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc
main.m -o main?arm64.cpp (?機)
三.分析c++文件

- 從上圖可以看出對象在底層的本質(zhì)是一個結構體
-
跟蹤NSObject_IMPL結構類型可以看到如圖下:
16238097133294.jpg

-
從上面圖可以得出objc 底層調(diào)用就是objc_object
16238101883395.jpg id class = [class new] 為什么我們id 類型可以獲取所有的屬性類型而且不需要加,因為他的底層就是id
@property (nonatomic, strong) NSString *nikeName
- 為什么屬性自帶set 和get 方法 根據(jù)底層跟蹤如下
static NSString * _I_LGPerson_nikeName(LGPerson * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_nikeName)); }
static void _I_LGPerson_setNikeName_(LGPerson * self, SEL _cmd, NSString *nikeName) { (*(NSString **)((char *)self + OBJC_IVAR_$_LGPerson$_nikeName)) = nikeName; }
- 總結:對象本質(zhì)就是一個結構體,屬性成員變量實現(xiàn)了get和和set方法.
- 流程分析 :
- LGPerson -->找到LGPerson_IMPL -->NSObject_IMPL--->Class
了解結構體和聯(lián)合體
- 結構體(struct)中所有變量是“共存”的——優(yōu)點是“有容乃?”,
全?;缺點是struct內(nèi)存空間的分配是粗放的,不管?不?,全分配 - 聯(lián)合體(union)中是各變量是“互斥”的——缺點就是不夠“包容”;但優(yōu)點是內(nèi)存使?更為精細靈活,也節(jié)省了內(nèi)存空間

- 從上圖輸出可以得出互斥更加節(jié)省內(nèi)存空間(BOOL front: 1; 1代表一個byte,8個byte=1字節(jié))
isa 的分析
-
以arm64為例16238138660021.jpg
nonpointer:表示是否對 isa 指針開啟指針優(yōu)化
0:純isa指針,1:不?是類對象地址,isa 中包含了類信息、對象的引?計數(shù)等has_assoc:關聯(lián)對象標志位,0沒有,1存在
has_cxx_dtor:該對象是否有 C++ 或者 Objc 的析構器,如果有析構函數(shù),則需要做析構邏輯,
如果沒有,則可以更快的釋放對象shiftcls: 存儲類指針的值。開啟指針優(yōu)化的情況下,在 arm64 架構中有 33 位?來存儲類指針
magic:?于調(diào)試器判斷當前對象是真的對象還是沒有初始化的空間
weakly_referenced:志對象是否被指向或者曾經(jīng)指向?個 ARC 的弱變量,沒有弱引?的對象可以更快釋放
deallocating:標志對象是否正在釋放內(nèi)存
has_sidetable_rc:當對象引?技術?于 10 時,則需要借?該變量存儲進位
extra_rc:當表示該對象的引?計數(shù)值,實際上是引?計數(shù)值減 1,
例如,如果對象的引?計數(shù)為 10,那么 extra_rc 為 9。如果引?計數(shù)?于 10,則需要使?到下?的 has_sidetable_rc。

用類的地址值與ISA_MASK 與就可以得出isa的信息
2 根據(jù)isa里面成員變量所占字節(jié)平移一樣可以算出isa的信息操作如下圖
-
圖一:
16238152287173.jpg -
圖二
16238161876908.jpg -
圖三
16238162534830.jpg 在圖一在摸儀器的中shiftcls位置在44,如圖二所示 左邊占17字節(jié) 右邊占 3字節(jié)
平分方式如圖三 得出結果如圖一輸出
new與init 的關聯(lián)
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}
- (id)init {
return _objc_rootInit(self);
}
- 從上看出new 不僅只是對對象進行初始化而且同時進行內(nèi)存分配,init只是單純的對對象進行初始化操作





