最近在准备着面试,发现了自己以前做的一篇使用汇编调试的笔记,若有错误,有望指正。
Swift可以用inout定义一个输入输出参数,让其可以在函数内部修改外部实参的值。其本质是Copy In Copy Out,是拷贝了实参的副本,然后在函数内对副本修改,函数结束时才对本体作出真正的修改。
那么OC也是如此吗?首先给出结论:是的,也是Copy In Copy Out.
使用指针变量作为方法参数时,方法内修改指向的地址值,查看执行方法前后该指针的变化。
调试代码如下:
看得出方法外和方法内的指针是不一样的,而且执行完方法后,方法外的那个指针指向的地址值才发生变化。
按照断点一步一步往下看,会发现刚执行完setupObj:会来到movq -0x30(%rbp), %rcx的位置:
- 【新的地址值】
rcx->rsi->objc_storeStrong->rbx(0x00007ffee71cbfe0存的值:0x0000000000000000) - 【原指针的值】
rdx->rdi->objc_storeStrong->r15(0x00007ffee71cbfe8这个地址) - 【赋值新地址】
rbx->r15(完成将0x00007ffee71cbfe8指向0x0000000000000000的操作)
确实是在方法结束时才对原指针指向的地址值作出修改,也就是说,类似inout一样是 Copy In Copy Out.
再次验证一下:
也是执行完方法后本体才会发生改变,所以方法内的指针确实是副本。
- PS:第一次修改属性值本体也同时改变是因为此时并没有修改指针指向的地址值。
注意
通过方法修改指针指向的地址值,是在方法结束时才会对指针真正的赋值!
例如在方法里面让外面的对象指针重新指向另一个对象,这时候方法都还没结束,调用了同步闭包想让外面立刻使用新的对象,然而这时候外面的对象却还是旧的,这样就有问题了哦!
所以在平时开发中,尤其是多线程任务,如果有如上对指针的操作需要注意一下!