一個關於字符串的打印實驗

第一部分

題目與答案

題目

image-20191204195734368

打印結果

image-20191204195802160

解析

  • 這裏的TLog是自己定義的一個宏函數#define TLog(_var) ({ NSString *name = @#_var; NSLog(@"%@: %@ -> %p : %@", name, [_var class], _var, _var); })
  • mutableString
    • 它是一個根據方法創建的可變字符串【廢話,可變字符串不能通過字面量創建,不然會報警告Incompatible pointer types initializing ‘NSMutableString *’ with an expression of type ‘NSString *’】
    • 所有的mutableString對象類型爲__NSCFString繼承鏈:__NSCFConstantString -> __NSCFString -> NSMutableString -> NSString -> NSObject
      • 它的特徵是它屬於一個普通的對象,不是字符串常量,創建時獲得1的引用計數
      • 通過 NSString 的 stringWithFormat 等方法創建的 NSString 對象一般都是這種類型,存儲在堆上
  • a
    • 我們對於可變字符串執行了copy操作,應該會生成一個不可變的副本,同時拷貝將會是深拷貝【可以這麼理解,如果將被拷貝的稱爲父本,拷貝結果稱爲子本,那麼我們要求是子本是不可變的,也就是父本變,子本不能變;由於我們的父本是可變的,所以我們只能選擇進行深拷貝,簡單的指針複製會出現子本跟着父本一起變得情況】
    • 所以我們的a會是一個完整的拷貝,所以地址肯定是跟mutableString不一樣的
      • 這裏可以深入探究下,我們的copy操作可以看作是一個使用stringWithFormat方法創建不可變字符串,由於我們的123是一個很簡單的字符串【不長也不帶中文】,所以我們生成的會是NSTaggedPointerString對象,它也是屬於唯一的,值一樣,地址就一樣
  • b
    • 我們對於可變字符串進行了mutableCopy的操作,應該要生成一個可變的副本,顯然也是深拷貝
    • 因此我們的b也是一個完整的拷貝,地址和mutableString,是不一樣的
    • 那麼和a會不會是一樣的呢?
      • 也不會
      • 因爲mutableCopy的操作就類似於用NSMutableString的方法去創建字符串,只會生成__NSCFString類型的
      • 它就相當於是一個普通對象,存在堆上,創建100個地址也是各不相同
  • c
    • c和b的解釋完全一樣
  • d
    • d和a的情況一模一樣
  • string
    • string是我們使用字面量語法創建的字符串
    • 字面量語法創建的就會是一個__NSCFConstantString,就是我們說的存在常量區的那種
    • 他也是獨一份,值一樣,地址就一樣

總結

  • 這已經沒什麼好往下寫的了,總結一下【默認深拷貝的情況】
  • copy:
    • copy方法的本質就是用NSString的stringWithFormat方法創建的不可變字符串
    • 它遵循其看人下菜的本質,對於不同的字符串,會生成不同的類型【其實也就__NSCFString和NSTaggedPointerString兩種】
  • mutableCopy:
    • mutableCopy方法的本質就是用NSMutableString的stringWithFormat方法創建的可變字符串
    • 它遵循着一根筋的本質,對於所有字符串,都只會生成__NSCFString這一種類型
  • 是的,這些情況只和調用方法的本質有關,和方法調用者,接收的指針類型都沒有關係

第二部分

題目與答案

題目

image-20191204210046283

打印結果

image-20191204211434681

總結

  • 這個原因比較簡單,就不具體一個個分析了
  • 對於copy關鍵字,不管我們用它修飾什麼對象,對於賦值給這個屬性的對象:
    • 如果是不可變對象:copy相當於strong,只會給該對象的引用計數加1,不會創建副本
    • 如果是可變對象:會創建一個不可變的副本,這裏相當於使用了copy方法,符合上面我們說的copy特性

附言

  • 想要理解這篇文章我們在探究什麼,你需要了解內存區,引用計數,NSString繼承鏈,taggedpointer優化機制
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章