说说OC参数传递的那些坑

有一些原本我们认为很基础的,而且很理所当然的,在实践之后才发现,麻蛋原来是这样

回顾一下c语言的参数传递

C语言中的参数传递

1、传值方式
原理:形参和实参占不同内存单元,传递的实际上是实参变量或表达式的一个拷贝副本,将这个副本值传给形参,形参内存单元内容保存的正是这个副本值,相当于给形参进行初始化,形参的值发生变化也不会传回给实参,因此是单向传递。
例如:

 void increase(int x)
 {
 x++;
 }

当在主函数中调用上面这个函数时,会在ncrease函数内存栈中为形参x分配一个内存单元,然后把实参的值传到这个内存单元中,相当于给形参初初化了,然后形参x自增1,它改变的仅仅是形参内存单元中的内容,而实参内存单元中的内容并没有改变。当被调用函数执行完毕后,形参所分配的内存单元也被收回。

2、传地址方式
原理:和传值方式一样,当调用函数时也要为形参分配内存,被调函数执行完毕后也要收回内存。不同的是传递的是实参变量地址的拷贝值,而不是实参变量的值,在被调函数中对地址所指对象的操作会改变实参的值。但是形参的内容即存放的实参变量地址并不会改变。
** OC中传递对象就是用这种方式呀,但是并没有被改变 我很疑惑**
例如:

 void increase(int * x)
 {
(*x)++;
 }
 int main()
 {
 int i,*x;
 i=10;
 *x=20;
 increase(&i);//如果定义的不是指针变量,那变要加上个取址号&,当然如果形参实参是数组的话,直接用数组名即可,因为数组名本身代表的就是数组的首地址
 increase(x);
 }

主函数调用被调函数后,主函数中的i和*x的值都会改变。

OC参数传递

NSString

先看看测试的代码


- (void)viewDidLoad {
  [super viewDidLoad];
 
  NSString *str = @"viewDidLoad";
  NSLog(@"viewDidLoad 改变前:%@",str);
  [self changNSString:str];
  NSLog(@"viewDidLoad 改变后:%@",str);
 
}
- (void)changNSString:(NSString *)str {
  NSLog(@"changNSString 改变前:%@",str);
  str = @"changNSString";
  NSLog(@"changNSString 改变后:%@",str);
}

大家觉得NSLog(@"viewDidLoad 改变后:%@",str);会打印什么.
** 可以改变str的值么**
经过测试,** str ** 经过函数changNSString的修改后根本没有改变


**2016-04-01 18:01:06.762 CommentDemo[8807:186874] viewDidLoad ****改变前****:viewDidLoad**
**2016-04-01 18:01:06.762 CommentDemo[8807:186874] changNSString ****改变前****:viewDidLoad**
**2016-04-01 18:01:06.762 CommentDemo[8807:186874] changNSString ****改变后****:changNSString**
**2016-04-01 18:01:06.762 CommentDemo[8807:186874] viewDidLoad ****改变后****:viewDidLoad**

这完全不符合常理呀!这是传递的地址呀.

NSMutableString

之后我换可变的字符串对象测试了一下:

- (void)viewDidLoad {
  [super viewDidLoad];
 
  NSMutableString *mStr = [NSMutableString stringWithString:@"viewDidLoad"];
  NSLog(@"viewDidLoad 改变前:%@",mStr);
  [self changeMutableString:mStr];
  NSLog(@"viewDidLoad 改变后:%@",mStr);
}

- (void)changeMutableString:(NSMutableString *)mStr {
  NSLog(@"changNSMutableString 改变前:%@",mStr);
  mStr = [NSMutableString stringWithString:@"changeMutableString"];
  NSLog(@"changNSMutableString 改变后:%@",mStr);
}

测试结果


**2016-04-01 18:07:33.382 CommentDemo[8856:191232] viewDidLoad ****改变前****:viewDidLoad**
**2016-04-01 18:07:33.383 CommentDemo[8856:191232] changNSMutableString ****改变前****:viewDidLoad**
**2016-04-01 18:07:33.383 CommentDemo[8856:191232] changNSMutableString ****改变后****:changeMutableString**
**2016-04-01 18:07:33.383 CommentDemo[8856:191232] viewDidLoad ****改变后****:viewDidLoad**

** 同样没有改变 **

NSMutableArray

后来我换了可变的数组

- (void)viewDidLoad {
  [super viewDidLoad];
 
  NSMutableArray *mArray = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
  for (NSString *str in mArray) {
    NSLog(@"viewDidLoad 改变前 %@",str);
  }
 
  [self changeMutableArray:mArray];
 
  for (NSString *str in mArray) {
    NSLog(@"viewDidLoad 改变后 %@",str);
  }
 
 
}
- (void)changeMutableArray:(NSMutableArray *)array {
  [array addObject:@"3"];
  for (NSString *str in array) {
    NSLog(@"changeMutableArray %@",str);
  }
}

测试结果


**2016-04-01 18:16:24.259 CommentDemo[8925:196443] viewDidLoad ****改变前**** 1**
**2016-04-01 18:16:24.259 CommentDemo[8925:196443] viewDidLoad ****改变前**** 2**
**2016-04-01 18:16:24.259 CommentDemo[8925:196443] changeMutableArray 1**
**2016-04-01 18:16:24.260 CommentDemo[8925:196443] changeMutableArray 2**
**2016-04-01 18:16:24.260 CommentDemo[8925:196443] changeMutableArray 3**
**2016-04-01 18:16:24.260 CommentDemo[8925:196443] viewDidLoad ****改变后**** 1**
**2016-04-01 18:16:24.260 CommentDemo[8925:196443] viewDidLoad ****改变后**** 2**
**2016-04-01 18:16:24.260 CommentDemo[8925:196443] viewDidLoad ****改变后**** 3**

** 值他妈的改变了 **

经过测试,可以知道在OC中,看似对象是声明为指针类型(* Str),由于传递的时候我们没有用取地址(&).结果根本没有改变. 我开始怀疑传递的是不是地址了.是不是因为自始至终没有用到过取地址符.

然后自己改为了如下方式,就能够改变传进来的值了

能够改变传递的值

NSString正常改变

- (void)viewDidLoad {
  [super viewDidLoad];
 
  NSString *str = @"viewDidLoad";
  NSLog(@"viewDidLoad 改变前:%@",str);
  [self changNSString:&str];
  NSLog(@"viewDidLoad 改变后:%@",str);
 
 
}
- (void)changNSString:(NSString **)str {
  NSLog(@"changNSString 改变前:%@",*str);
  *str = @"changNSString";
  NSLog(@"changNSString 改变后:%@",*str);
}

测试结果


**2016-04-01 18:27:33.139 CommentDemo[8993:203983] viewDidLoad ****改变前****:viewDidLoad**
**2016-04-01 18:27:33.139 CommentDemo[8993:203983] changNSString ****改变前****:viewDidLoad**
**2016-04-01 18:27:33.139 CommentDemo[8993:203983] changNSString ****改变后****:changNSString**
**2016-04-01 18:27:33.139 CommentDemo[8993:203983] viewDidLoad ****改变后****:changNSString**

总结

看到这种状况我能说服自己的就是:
NSString *str = @"viewDidLoad";这样的定义在OC中其实就是类似于c语言的普通变量而已,而不是指针变量.智商有点不够用.

原因或许很简单

看似和c语言地址传递一样,同样是*传递。但c语言拿到这个指针之后取了指针指向的内容并改变了内容。而oc中我们习惯直接str =✘。让这个指针指向了新的地方。并没有改变函数外面原来指针指向的内容。这点特别重要,指针传过来那个str本质是值传递,相当于copy了一份。所以在change函数里面的str并不是外面的str。哈哈。今天有点短路。

还是一点,c语言中改变了传进来指针原来指向的内容,而oc中只改变了新指针指向的地方。



2016-4-11
谈谈自定义对象,给对象赋值又是怎样的.
经过测试,给对象的属性复制能够在另一个函数改变其属性
看看测试结果

**2016-04-11 14:19:47.708 CommentDemo[3027:130157] name: xiaomao, age: 17**
**2016-04-11 14:19:47.709 CommentDemo[3027:130157] name: newxiaomao, age: 89**
**2016-04-11 14:19:47.709 CommentDemo[3027:130157] name: newxiaomao, age: 89**

测试代码

- (void)createCat {
    Cat *cat = [Cat new];
    cat.name = @"xiaomao";
    cat.age = @"17";
    NSLog(@"%@",cat);
    [self catObjectTest:cat];
    NSLog(@"%@",cat);
}
- (void)catObjectTest:(Cat *)cat {
    cat.name = @"newxiaomao";
    cat.age = @"89";
    NSLog(@"%@",cat);
}

分析

当我在调用对象的属性进行赋值的时候,其实是调用getter/setter方法,通过这样的赋值,属性值肯定改变呀.O(∩_∩)O~

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

推荐阅读更多精彩内容