-
Notifications
You must be signed in to change notification settings - Fork 0
iOS 各种copy原理
miaohy edited this page Dec 13, 2020
·
2 revisions
1、属性中的copy (属性中执行copy后可以防止外面可变类型变量变化对内部属性的改动)
@interface Man :NSObject{
@public NSString *provar;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSMutableString *hobby; //会对原对象执行copy操作,并且hobby不能再改变
@end
@interface Person :NSObject
@property (nonatomic, strong) NSString *name;
@end
//创建可变类型的字符串
NSMutableString *str = [NSMutableString stringWithString:@"sdss"];
Person *pp = [[Person alloc] init];
[pp testcount];
pp.name = str;
Man *bb = [[Man alloc] init];
bb->provar = str; // 不会生成setter方法,所以只是单纯的赋值,不操作引用计数,只是将指针指向了原来的内存
bb.name = str; //将可变类型字符串赋值给bb的name,这时候会执行属性setter方法时会执行copy
bb.hobby = str;
[bb.hobby appendString:@"g"]; //会报Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with appendString:
[str appendString:@"dsddf"];
运行后bb.name 输出sdss,而pp.name输出为sdssdsddf
终端执行 clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.2.sdk -Os -S -fobjc-arc -emit-llvm main.m -o main.ll 查看main.ll 文件
//Person的setter方法执行str的是retain,将name的指针指向了str指向的内存
define internal void @"\01-[Person setName:]"(%0* nocapture %0, i8* nocapture readnone %1, %1* %2) #4 {
%4 = bitcast %0* %0 to i8*
%5 = getelementptr inbounds i8, i8* %4, i64 8
%6 = bitcast i8* %5 to %1**
%7 = bitcast %1* %2 to i8*
%8 = tail call i8* @llvm.objc.retain(i8* %7) #5
%9 = bitcast i8* %5 to i8**
%10 = load i8*, i8** %9, align 8, !tbaa !11
store %1* %2, %1** %6, align 8, !tbaa !11
tail call void @llvm.objc.release(i8* %10) #5
ret void
}
//Man的setter方法执行的是str的copy操作,将str中内容重新拷贝了一份,并将name指针指向了新生成的内存
define internal void @"\01-[Man setName:]"(%2* %0, i8* %1, %1* %2) #1 {
%4 = bitcast %2* %0 to i8*
%5 = bitcast %1* %2 to i8*
tail call void @objc_setProperty_nonatomic_copy(i8* %4, i8* %1, i8* %5, i64 8) #7, !clang.arc.no_objc_arc_exceptions !10
ret void
}
NSString *strr = @"tttttttttttttttttttttttttttttttttttttttttttttttttttt";
NSString *dd = [strr copy]; //指针的copy
NSString *p = [strr mutableCopy];//内存的copy
NSMutableString *str = [NSMutableString stringWithString:@"sdssdsfsfdsgdfggdghdhggjhjgjghgjghfffddssgssdfsdfsdfsfsffs"];
NSMutableString *cc = [str mutableCopy]; //执行完后cc还可以改变 内存的copy
NSMutableString *dd = [str copy];//执行完后dd是不可以变的 内存的copy
[cc appendString:@"dffs"];
copy伪代码
void copy(src*,dest*){ 1、判断src是否可变类型,不可变类型,就让dest指针指向原来的src指向的内存空间 2、src是可变类型,那么开辟新的内存空间,然后将src中内容赋值到新开辟内存,然后dest指向新开辟固定内存 }
void mutablecopy(src*, dest*){ 1、判断src 是否是可变类型,不可变类型,开辟新的内存,赋值src到新的内存空间,dest指向新的固定大小内存空间 2、src可变类型,开品新的内存空间,赋值src到新的内存空间,dest指向新的可变内存空间 }
如何创建可变内存空间,如何创建不可变内存空间
//malloc(需要的内存空间:字节空间);
int *pTemp = (int*)malloc(1 * sizeof(int));
pTemp [1] = 10;//*(pTemp+1) = 10;
//对已经存在的空间进行改变
int *pRTemp = (int *)realloc(pTemp,2 * sizeof(int));
if(prtemp == NULL){
free(pTemp);
}
pTemp = pRTemp;
realloc使用总结:
- realloc失败的时候,返回NULL。
- realloc失败的时候,原来的内存不改变,不会释放也不会移动。
- 假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址; 假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被自动 free 掉,realloc返回新内存的地址。
- 如果size为0,效果等同于 free ()。这里需要注意的是只对 指针 本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防 内存泄露 。
- 传递给realloc的 指针 必须是先前通过 malloc (), calloc (), 或realloc()分配的。