NSString的記憶體管理問題

2021-07-05 11:47:40 字數 4339 閱讀 9009

nsstring是乙個不可變的字串物件。這不是表示這個物件宣告的變數的值不可變,而是表示它初始化以後,你不能改變該變數所分配的記憶體中的值,但你可以重新分配該變數所處的記憶體空間。

生成乙個nsstring型別的字串有三種方法:

方法1.直接賦值:     nsstring *str1 = @"my string"; 

方法2.類函式初始化生成:     nsstring *str2 = [nsstring stringwithstring:@"my string"];

方法3.例項方法初始化生成:   nsstring *str3 = [[nsstring alloc] initwithstring:@"my string"];

nsstring

*str4 = [[

nsstring

alloc

]initwithformat

:@"my string"];

區別1: 方法一生成字串時,不會初始化記憶體空間,所以使用結束後不會釋放記憶體;

而其他三個都會初始化記憶體空間,使用結束後要釋放記憶體;

在釋放記憶體時方法2和3也不同,方法2是autorelease型別,記憶體由系統釋放;方法3則必須手動釋放

區別2:用format初始化

的字串,需要初始化一段動態記憶體空間,如:

0x6a42a40;

而用string宣告的字串,初始化的是常量記憶體區,如:

0x46a8

,常量記憶體區的位址,只要值相同,占用的位址空間是一致的。

所以str3和str1的位址一致,但是str4和str1的位址不一致。

前幾天去面試,被問到了nsstring屬性宣告中的copy和retain具體區別,對記憶體計數的影響,汗,當時沒整明白,也沒答出來,只知道nsstring一般用copy.

首先做以下幾個變數宣告:

@property (retain, nonatomic) nsstring *retainstr;

@property (copy, nonatomic)   nsstring *copystr;

@property (retain, nonatomic) nsmutablestring *retainmstr;

@property (copy, nonatomic)   nsmutablestring *copymstr;

實現**如下:

nsmutablestring *mstr = [nsmutablestring string];

[mstr setstring:@"我沒變"];

self.retainstr   = mstr;

self.copystr     = mstr;

self.retainmstr = mstr;

self.copymstr   = mstr;

nslog(@"retainstr:%@",  self.retainstr);

nslog(@"copystr:%@",    self.copystr);

nslog(@"retainmstr:%@", self.retainmstr);

nslog(@"copymstr:%@",   self.copymstr);

nslog(@"\n");

[mstr setstring:@"我變了"];

nslog(@"retainstr:%@",  self.retainstr);

nslog(@"copystr:%@",    self.copystr);

nslog(@"retainmstr:%@", self.retainmstr);

nslog(@"copymstr:%@",   self.copymstr);

nslog(@"\n");

nsstring *str = @"我來了";//[[nsstring alloc] initwithformat:@"我來了"];//兩種方式都一樣。

self.retainstr  = str;

self.copystr    = str;

self.retainmstr = [str mutablecopy];

self.copymstr   = [str mutablecopy];

nslog(@"retainstr:%@",  self.retainstr);

nslog(@"copystr:%@",    self.copystr);

nslog(@"retainmstr:%@", self.retainmstr);

nslog(@"copymstr:%@",   self.copymstr);

nslog(@"\n");

str =@"我走了";//[[nsstringalloc] initwithformat:@"我走了"];//兩種方式都一樣

nslog(@"retainstr:%@",  self.retainstr);

nslog(@"copystr:%@",    self.copystr);

nslog(@"retainmstr:%@", self.retainmstr);

nslog(@"copymstr:%@",   self.copymstr);

nslog(@"\n");

列印結果如下:

2012-10-12 13:53:14.858 stringdemo[1515:11303] retainstr:我沒變

2012-10-12 13:53:14.860 stringdemo[1515:11303] copystr:我沒變

2012-10-12 13:53:14.861 stringdemo[1515:11303] retainmstr:我沒變

2012-10-12 13:53:14.862 stringdemo[1515:11303] copymstr:我沒變

2012-10-12 13:53:14.863 stringdemo[1515:11303] 

2012-10-12 13:53:14.864 stringdemo[1515:11303] retainstr:我變了

2012-10-12 13:53:14.865 stringdemo[1515:11303] copystr:我沒變

2012-10-12 13:53:14.866 stringdemo[1515:11303] retainmstr:我變了

2012-10-12 13:53:14.867 stringdemo[1515:11303] copymstr:我沒變

2012-10-12 13:53:14.868 stringdemo[1515:11303] 

2012-10-12 13:53:14.869 stringdemo[1515:11303] retainstr:我來了

2012-10-12 13:53:14.869 stringdemo[1515:11303] copystr:我來了

2012-10-12 13:53:14.870 stringdemo[1515:11303] retainmstr:我來了

2012-10-12 13:53:14.871 stringdemo[1515:11303] copymstr:我來了

2012-10-12 13:53:14.872 stringdemo[1515:11303] 

2012-10-12 13:53:14.873 stringdemo[1515:11303] retainstr:我來了

2012-10-12 13:53:14.874 stringdemo[1515:11303] copystr:我來了

2012-10-12 13:53:14.875 stringdemo[1515:11303] retainmstr:我來了

2012-10-12 13:53:14.876 stringdemo[1515:11303] copymstr:我來了

由此可以看出:對源頭是nsmutablestring的字串,retain僅僅是指標引用,增加了引用計數器,這樣源頭改變的時候,用這種retain方式宣告的變數(無論被賦值的變數是可變的還是不可變的),它也會跟著改變;而copy宣告的變數,它不會跟著源頭改變,它實際上是深拷貝。對源頭是nsstring的字串,無論是retain宣告的變數還是copy宣告的變數,當第二次源頭的字串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指標引用,也就是淺拷貝。

另外說明一下,這兩者對記憶體計數的影響都是一樣的,都會增加記憶體引用計數,都需要在最後的時候做處理。

其實說白了,對字串為啥要用這兩種方式?我覺得還是乙個安全問題,比如宣告的乙個nsstring *str變數,然後把乙個nsmutablestring *mstr變數的賦值給它了,如果要求str跟著mstr變化,那麼就用retain;如果str不能跟著mstr一起變化,那就用copy。而對於要把nsstring型別的字串賦值給str,那兩都沒啥區別。不會影響安全性,記憶體管理也一樣。

NSString的記憶體管理問題

nsstring是乙個不可變的字串物件。這不是表示這個物件宣告的變數的值不可變,而是表示它初始化以後,你不能改變該變數所分配的記憶體中的值,但你可以重新分配該變數所處的記憶體空間。生成乙個nsstring型別的字串有三種方法 方法1.直接賦值 nsstring str1 my string 方法2....

NSString的記憶體實現

nsstring等foundation框架提供的類的記憶體管理 1 字串的常量池 在資料區 2 nsstring str1 abc nsstring str2 nsstring stringwithstring abc nsstring str3 nsstring alloc initwithstr...

NSString中的數字問題

在寫學生管理系統的時候,需要判斷student類中 學生姓名中是否有數字,學號 年齡 成績是否全為數字,而在定義時把它們都設為了nsstring,所以需要從nsstring中提取出,或判斷出數字。用於判斷學生姓名 用來判斷姓名和班級 是否含有數字 nscharacterset characterse...