日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

copy与mutableCopy的内存管理剖析

發(fā)布時(shí)間:2025/3/19 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 copy与mutableCopy的内存管理剖析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

title: copy與mutableCopy的內(nèi)存管理剖析
date: 2016-04-24 16:50:04

tags: copy

copy與mutableCopy相關(guān)的內(nèi)存管理

不知道為什么一說這個(gè),很多人都拿NSString和NSMutableString做測(cè)試,我想最直接的是因?yàn)槌S糜謱?shí)現(xiàn)了copy和mutableCopy的代理,但是NSString類的其實(shí)比較特殊,不應(yīng)該拿NSString來測(cè)試,所以本文拿實(shí)現(xiàn)代理的NSURLRequest來做測(cè)試。

immutableObject:

非集合的

NSURL *url = [[NSURL alloc] initWithString:@"ceshi"];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url];
NSLog(@"urlReqeust:%@, urlRequestRec:%ld", urlRequest, [urlRequest retainCount]);
//log: urlReqeust: { URL: ceshi }, urlRequestRec:1

NSURLRequest *urlRequest1 = [urlRequest copy];
NSLog(@"urlRequest1:%@, urlRequest1:%ld", urlRequest1, [urlRequest1 retainCount]);
// log: urlRequest1: { URL: ceshi }, urlRequest1:2

總結(jié):immutableObject做copy時(shí),做的是淺copy,也就是說只是所指向的對(duì)象的內(nèi)存計(jì)數(shù)器增加了1,所以如果urlRequest1重新賦值時(shí),需要做下release把之前所指的對(duì)象的內(nèi)存計(jì)數(shù)器減1,否則就會(huì)有內(nèi)存泄露。如下:

[urlRequest1 release], urlRequest1 = nil;
// 此時(shí)urlRequest所指對(duì)象計(jì)數(shù)器為1,urlRequest1為nil
urlRequest1 = [NSURLRequest requestWithURL:[NSURL URLWithString:@"ceshi2"]];
// 此時(shí)urlRequest1指向新的對(duì)象,指向的對(duì)象的計(jì)數(shù)器為1
集合的

NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
// log: =====array:0x7fb2a8f0d2b0,arrayRec:2, =====copyArray:0x7fb2a8f0d2b0,copyArrayRec:2, ======mCopyArry:0x7fb2a8e10ef0, mCopyArrayRec:1

// 有bug,必須要做copyArray的release

copyArray = @[@"a",@"d"];
NSLog(@"array:%@,copyArr:%@,mCopyArray:%@", array, copyArray, mCopyArray);
// log: =====array:0x7fb2a8f0d2b0,arrayRec:2, =====copyArray:0x7fb2a8f1b980,copyArrayRec:1, ======mCopyArry:0x7fb2a8e10ef0, mCopyArrayRec:1

與immutable的非集合一樣,copy將直接增加指針指向?qū)ο蟮囊糜?jì)數(shù)器(集合的話:各元素的指針計(jì)數(shù)器都增加了1)。所以在copyArray更改前,必須要做release,否則會(huì)有內(nèi)存泄漏

mutableObject

非集合的

NSURL *url = [[NSURL alloc] initWithString:@"ceshi"]; NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:url]; NSLog(@"urlReqeust:%@, urlRequestRec:%ld\r", urlRequest, [urlRequest retainCount]); // log: urlReqeust:<NSURLRequest: 0x7f98dac07e00> { URL: ceshi }, urlRequestRec:1NSMutableURLRequest *mutableRequest = [urlRequest mutableCopy]; NSLog(@"mutableRequest:%@, mutableRequest:%ld", mutableRequest, [mutableRequest retainCount]); // log: mutableRequest:<NSMutableURLRequest: 0x7f98daf07390> { URL: ceshi }, mutableRequest:1NSMutableURLRequest *mutableRequest1 = [mutableRequest mutableCopy]; NSLog(@"mutableRequest1:%@, mutableRequest1:%ld", mutableRequest1, [mutableRequest1 retainCount]); // log: mutableRequest1:<NSMutableURLRequest: 0x7f98dac674f0> { URL: ceshi }, mutableRequest1:1

集合的


NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
// log: =====array:0x7fbbd3d0d730,arrayRec:1, =====copyArray:0x7fbbd3d19610,copyArrayRec:1, ======mCopyArry:0x7fbbd3d18ad0, mCopyArrayRec:1

總結(jié):mutableObject的復(fù)制是深復(fù)制,直接創(chuàng)建一個(gè)新的內(nèi)存地址來復(fù)制其內(nèi)容(在集合中把各個(gè)元素的內(nèi)容都賦值了一遍)。 與之前的被復(fù)制項(xiàng)無任何關(guān)系。

匯總:

  • [immutableObject copy] // 淺復(fù)制
  • [immutableObject mutableCopy] //深復(fù)制
  • [mutableObject copy] //深復(fù)制
  • [mutableObject mutableCopy] //深復(fù)制

特殊的NSString


NSString *str1 = @"abc";
NSString *str2 = @"abc";
NSString *str3 = [[NSString alloc] initWithString:@"abc"];
NSString *str4 = [str1 copy];
NSString *str5 = [[NSString alloc] initWithString:@"abc"];
NSString *str6 = [str1 mutableCopy];

//輸出內(nèi)存中的地址
NSLog(@"str1: %p", str1);
NSLog(@"str2: %p", str2);
NSLog(@"str3: %p", str3);
NSLog(@"str4: %p", str4);
NSLog(@"str5: %p", str5);
NSLog(@"str6: %p", str6);

猜下結(jié)果:

2016-04-24 22:41:50.629 TestCopy[2094:229125] str1: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str2: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str3: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str4: 0x1081af070
2016-04-24 22:41:50.630 TestCopy[2094:229125] str5: 0x1081af070
2016-04-24 22:41:50.631 TestCopy[2094:229125] str6: 0x7fb1d3f0ce70

我的理解:
NSString在程序中使用非常大,所以在immutable的copy和mutableCopy的原理下,為了系統(tǒng)性能的考慮,增加了只要是NSString存在,則直接把字符串地址付給使用者即可。如果此時(shí)str2=@"abdt"了,則直接拿生成的abdt的地址賦值給str2即可。

NSMutableString與immutableObj類似


NSMutableString *str1 = [NSMutableString stringWithFormat:@"abc"];
NSMutableString *str2 = [[NSMutableString alloc] initWithString:@"abc"];
NSMutableString *str3 = [str1 copy];
NSMutableString *str4 = [str1 mutableCopy];

//輸出內(nèi)存中的地址
NSLog(@"str1: %p, reC:%ld", str1, [str1 retainCount]);
NSLog(@"str2: %p, reC:%ld", str2, [str2 retainCount]);
NSLog(@"str3: %p", str3);
NSLog(@"str4: %p", str4);

log:
2016-04-24 22:58:42.319 TestCopy[2164:240308] str1: 0x7fa7ebca0c50, reC:1
2016-04-24 22:58:42.319 TestCopy[2164:240308] str2: 0x7fa7ebca8560, reC:1
2016-04-24 22:58:42.319 TestCopy[2164:240308] str3: 0xa000000006362613
2016-04-24 22:58:42.320 TestCopy[2164:240308] str4: 0x7fa7ebca7ed0

最后看2段代碼:


//UserEntity.h
@interface UserEntity : NSObject
@property(strong, nonatomic) NSString *name;
@end
UserEntity *userEntity = [UserEntity new];
//創(chuàng)建mutable類型的字符串
NSMutableString *showName = [[NSMutableString alloc] initWithString:@"tutuge"];
//先保存“tutuge”字符串到userEntity的name
userEntity.name = showName;
//修改showName
[showName appendString:@" blog"];
//輸出userEntity的name屬性
NSLog(@"Name: %@", userEntity.name);

輸出為:tutuge blog

如果更改為:@interface UserEntity : NSObject
@property(copy, nonatomic) NSString *name;
@end

則輸出為: tutuge

總結(jié)

以上是生活随笔為你收集整理的copy与mutableCopy的内存管理剖析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。