OC中对指针的深度理解

指针,顾名思义,在现实生活中就是指明特定的值或者特定的方向,如生活中常见的湿度表上的指针,指南针上的指针,一个指明当前湿度的值,一个指明南北方向,但是指针本身并不是值也不是方向,只是一种表示工具。

那么在计算机编程语言中的指针,也是一样的功能,只是在编程语言中的指针,既不是指明方向,也不是表明值,而是指向一块内存地址,即指向对象的对象。

什么叫指向对象的对象?就好像每个中国公民都有一个身份证,如果把人比作对象,那么身份证上的身份证号码,就是这个人的地址。

计算机中,每一个对象都要占用一块内存空间,因此每一个对象都会对应一个内存地址。就好像每一个人都有身份证,每个身份证上都有一个身份证号码一样。

因此,指针也是一个对象,指针也有它自己的内存地址,是一个特殊的对象,负责特殊的工作,就好像总经理助理。你想见总经理没门,有什么事都经过总经理助理传达,找到了总经理助理就相当于找到了总经理。

所以,总经理有身份证,总经理助理也有身份证,说白了,也就是指向另一个人的人,或者代表另一个人的人。

那么在OC中方法外向方法内传值,到底传的是什么?

第一种情况,简单变量
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *str = @"12345";
    NSLog(@"A-%@--对象:%p--指针:%p",str,str,&str);
    Object_1 *objec = [[Object_1 alloc]init];
    [objec stringChangeByStr2:str];
    NSLog(@"A-%@--对象:%p--指针:%p",str,str,&str);
}
- (void)stringChangeByStr2:(NSString *)str{
    NSLog(@"B-%@--对象:%p--指针:%p",str,str,&str);
    str = @"45678";
    NSLog(@"B-%@--对象:%p--指针:%p",str,str,&str);
}

打印结果:

A-12345--对象:0x105c08068--指针:0x7ffee9ff8178
B-12345--对象:0x105c08068--指针:0x7ffee9ff8128
B-45678--对象:0x105c080a8--指针:0x7ffee9ff8128
A-12345--对象:0x105c08068--指针:0x7ffee9ff8178

由打印结果可以看出:
1、指针的地址发生改变。从A到B,即方法外到方法内,指针发生改变,因此,变量由方法外传到方法内的时候,会新建一个指针来指向目标对象,目标对象的引用计数会加一。
2、目标对象发生改变。对str赋值之后,对象的地址发生改变,说明方法内str指针的指向发生了改变,指向一块新的内存地址,这块内存地址所代表的值是字符串@“45678”,引用计数器的变化是,对象“45678”的引用计数加一,对象“ 12345”的引用计数减一。
3、赋值改变的是指针的指向,而没有直接修改对象的内容。
4、方法外的指针,在方法调用前后,没有发生改变,指针所指向的对象,也没有发生改变。

第二种情况,复合变量
- (void)viewDidLoad {
    [super viewDidLoad];
    Object_1 *objec = [[Object_1 alloc]init];
    Object_2 *obj = [[Object_2 alloc]init];
    obj.objcStr = @"09876";
    NSLog(@"6-%@--对象:%p--指针:%p--%p",obj.objcStr,obj,&obj,obj.objcStr);
    [objec changeValueWith:obj];
    NSLog(@"6-%@--对象:%p--指针:%p--%p",obj.objcStr,obj,&obj,obj.objcStr);

}
- (void)changeValueWith:(Object_2 *)obj{
    NSLog(@"5-%@--对象:%p--指针:%p--%p",obj.objcStr,obj,&obj,obj.objcStr);
    obj.objcStr = @"45678";
    NSLog(@"5-%@--对象:%p--指针:%p--%p",obj.objcStr,obj,&obj,obj.objcStr);
}

打印结果:

6-09876--对象:0x600000af5600--指针:0x7ffee71a2168--0x108a5e0a8
5-09876--对象:0x600000af5600--指针:0x7ffee71a20e8--0x108a5e0a8
5-45678--对象:0x600000af5600--指针:0x7ffee71a20e8--0x108a5e0e8
6-45678--对象:0x600000af5600--指针:0x7ffee71a2168--0x108a5e0e8

由打印结果可以看出:
1、目标对象的地址一直没有改变,说明对象没有被改变。
2、指针的地址改变了,方法内和方法外的地址不一样,说明方法内新建了一个指针指向目标对象,因此,这个时候,是有两个指针指向同一个对象,对象的引用计数加一。
3、执行obj.objcStr = @"45678"之后,objcStr对象的地址改变了,说明指针objcStr的指向改变了,对objcStr赋值,其实就是改变objcStr的指向,使其指向一个新的内存地址,代表一个新的对象。
4、方法外的objcStr的值也被修改。那么这种情况就打破了OC的方法只能return一个返回值的尴尬。也就是说,我想要得到调用方法之后的处理结果,并不一定就只能用返回值来返回,我可以通过直接修改变量指针的赋值来实现。

结论

从第一和第二种情况能看出,想要从一个方法中获得多个返回值,只要把需要的返回值,用一个对象包装一下,就能直接得到方法调用处理之后的结果。

那么问题来了,这种方式的原理是什么?原理就与OC的内存管理机制相关了。

在第一种情况中,

赋值之前,方法外str指针指向对象“12345”,方法内str指针也指向“12345”,因为这个时候目标对象的地址都是0x105c08068

赋值之后,方法内指针赋值“45678”,方法内str指针指向的内存地址是0x105c080a8,指针的指向已经改变。

这个时候,方法外的指针指向内存地址A,方法内的指针指向内存地址B,此时二者之间已经完全没有联系,两个独立的指针变量指向两个完全不一样的对象。

方法内的指针变量,在其作用域结束之后(方法的两个花括号之间),就要被release掉,即对象“45678”的引用计数减一,变成0,此时对象地址会被回收,同时对象被销毁。

既然对象“45678”在作用域结束之后,就被销毁了,那么,在作用域之外,自然就无法获取到对象“45678”

所以,从无法获取到对象“45678”的原因就能看出,获取不到是因为引用计数变为0,内存被回收了,那么如果想要拿到对象“45678”,方法就是不让引用计数变为0。

此时将目光转向第二种情况,

在这种情况下,我们在方法内修改了obj.objcStr之后,方法外依然能拿到obj.objcStr修改之后的值,原因也很简单,就是因为对象obj没有被释放掉。

方法外的指针指向对象obj的地址0x600000af5600,方法内的指针也指向对象obj的地址0x600000af5600,所以,此时的对象obj的引用计数为2。

我们修改了obj的成员变量的值,obj.objcStr = @"45678";只是对成员变量指针重新赋值,改变了成员变量的指针指向,但是并没有改变obj的引用情况,所以此时obj的引用计数还是2,方法内的obj指针依然指向对象地址0x600000af5600

当方法调用结束,目标对象0x600000af5600的引用计数减一,此时,方法外的obj指针还指着目标对象0x600000af5600,因此,目标对象的引用计数为1,依然被持有,因此不被释放,所以在方法外依然能够访问目标对象。因为目标对象依然存在,所以,目标对象的成员变量也依然被持有,所以也不会被释放。于是就能访问到obj.objcStr修改之后的值。

第三种情况,指针的指针

除了第二种情况之外,还有没有一种方法,把对象直接赋值给指针,但是却不被释放掉呢?

答案是当然有,那就是用指针的指针,即**point。这种方式的原理其实和第二种情况类似,就是把想要修改的对象,再包装一层。

例如

NSString *p = @“111111”;

意思就是新建一个NSString类型的指针变量p,使其指向对象@"111111"的地址,

于是就有:
1、p代表指针对象本身
2、*p代表指针指向的对象@"111111"
3、&p代表指针本身的地址

那么**a是什么呢?

例如:

NSString **a = &p;

意思就是新建一个NSString类型的二重指针变量a,使其指向指针对象p的地址。

于是就有:
1、a代表指针变量本身
2、*a代表指针所指向的指针对象p
3、**a代表指针指向的指针对象p所指向的对象@"111111",即*p
4、&a代表指针本身的地址

- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *str = @"12345";
    NSLog(@"1-%@--对象:%p--指针:%p",str,str,&str);
    Object_1 *objec = [[Object_1 alloc]init];
    [objec stringChangeByStr:&str];
}
- (void)stringChangeByStr:(NSString *__autoreleasing *)str{
    NSLog(@"2\n-- *str:%p\n--str:%p\n-- &str:%p",*str,str,&str);
}

打印结果

1-12345--对象:0x10208c068--指针:0x7ffeedb74178
2
-- *str:0x10208c068(指针p指向的对象)
--  str:0x7ffeedb74168(指针p的地址)
-- &str:0x7ffeedb74118(指针a的地址)

在OC实际应用中,用指针对象p访问p所指向的对象,即*p,所以在定义中和实际应用中有些许不同,绕的弯比较深,自行理解吧。。。。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,252评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,886评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,814评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,869评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,888评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,475评论 1 312
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,010评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,924评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,469评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,552评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,680评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,362评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,037评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,519评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,621评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,099评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,691评论 2 361

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,113评论 1 32
  • 307、setValue:forKey和setObject:forKey的区别是什么? 答:1, setObjec...
    AlanGe阅读 1,554评论 0 1
  • ———————————————回答好下面的足够了---------------------------------...
    恒爱DE问候阅读 1,720评论 0 4
  • 纪勇刚入学的时候,差点被老师以为是自闭症的孩子。他不会和同学交流,一着急你就会歇斯底里,入学刚刚一个月,学校举办国...
    教育and成长阅读 127评论 0 0
  • 生理方面,青春期正处在身体发育的关键期,对于网络上瘾者上网持续时间过长,超负荷的网络活动会导致大脑神经中枢持续处于...
    林深偶见鹿阅读 502评论 0 2