깊이 복사(mutable Copy)와 얕은 복사(copy) 설명

7825 단어 oc
간단하게 말하면 바늘이 있는 상황에서 얕은 복사는 바늘이 이미 존재하는 메모리를 가리키는 것을 증가시켰을 뿐이다.깊은 복사는 바늘을 늘리고 새 메모리를 신청해서 이 바늘이 새 메모리를 가리키도록 하는 것이다.
깊이 있는 복사를 사용하면 메모리를 방출할 때 얕은 복사를 할 때 같은 메모리를 반복적으로 방출하는 오류가 발생하지 않는다.
본문을 읽기 전에 우선copy와retain의 차이점copy와retain의 차이점을 이해한다.
copy는 새 대상을 만듭니다.retain은 포인터를 만듭니다. 인용 대상의 계수는 1입니다.copy 속성은 두 대상의 내용이 같고 새로운 대상retain은 1이며 기존 대상의 인용 계수와 상관없이 기존 대상은 변하지 않습니다.copy는 상하문에 대한 대상의 의존을 감소합니다.
retain 속성은 두 대상의 주소가 같다는 것을 나타낸다. (포인터를 만들고 포인터를 복사한다.) 내용은 당연히 같다. 이 대상의retain 값 +1 즉,retain은 포인터 복사이고,copy는 내용 복사이다.
물론 iOS에서 모든 대상이 copy,mutable Copy를 지원하는 것은 아니다. NSCopying 프로토콜을 준수하는 클래스는 copy 메시지를 보낼 수 있고, NSMutable Copying 프로토콜을 준수하는 클래스는 mutable Copy 메시지를 보낼 수 있다.
만약 상소 두 프로토콜을 준수하지 않고 코피나mutable Copy를 보냈다면 이상이 발생할 것입니다.
그러나 기본 iOS 클래스는 이 두 프로토콜을 준수하지 않았다.copy를 사용자 정의하려면 NSCopying을 준수하고 copyWithZone: 방법을 실현해야 합니다.
mutable Copy를 사용자 정의하려면 NSMutable Copying을 준수하고 mutable Copy WithZone: 방법을 실현해야 합니다.

1. 시스템의 비용기류 대상


NSString, NSNumber 등의 객체를 말합니다.  
  NSString *string = @"origion";
  NSString *stringCopy = [string copy];
  NSMutableString *stringMCopy = [string mutableCopy];
  [stringMCopy appendString:@"!!"];

메모리를 보면 string과stringCopy가 같은 메모리 영역을 가리키는 것을 알 수 있습니다. 이때 stringCopy의 인용 계수는string의 인용 계수와 같이 2입니다.한편stringMCopy는 우리가 말한 진정한 의미의 복제이다. 시스템은 그에게 새로운 메모리를 분배했지만 바늘이 가리키는 문자열은string이 가리키는 것과 같다.
다음 예를 참조하십시오.
    NSMutableString *string = [NSMutableString stringWithString: @"origion"];
    NSString *stringCopy = [string copy];
    NSMutableString *mStringCopy = [string copy];
    NSMutableString *stringMCopy = [string mutableCopy];
    [mStringCopy appendString:@"mm"];//error
    [string appendString:@" origion!"];
    [stringMCopy appendString:@"!!"];

네 개의 NSString 객체에 할당된 메모리는 모두 다릅니다.그러나 mStringCopy는 사실 imutable 대상이기 때문에 위에서 말한 것은 틀릴 수 있습니다.
시스템의 비용기류 대상에 대해 우리는 변할 수 없는 대상을 복제하면 코피는 바늘 복제(얕은 복사)와mutable Copy는 대상 복제(깊은 복사)라고 볼 수 있다.가변 대상을 복제하면 모두 깊이 복사하지만, 코피가 되돌아오는 대상은 가변적이지 않습니다.

2. 시스템의 컨테이너 클래스 객체


NSArray, NSDictionary 등을 나타냅니다.용기류 자체에 대해 위에서 논의한 결론도 적용되고 복제 후 용기 내 대상의 변화를 검토해야 한다.
copy는 가변 객체를 반환하고mutableCopy는 가변 객체를 반환합니다.
    NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
    NSArray *arrayCopy1 = [array1 copy];

array Copy1은 array와 같은 NSArray 대상(같은 대상을 가리키는 것)이고 array 안의 요소를 포함하여 같은 지침을 가리킨다.
    NSLog(@"array1 retain count: %d",[array1 retainCount]);
    NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);
    NSMutableArray *mArrayCopy1 = [array1 mutableCopy];

mArrayCopy1은 array1의 가변 복사본으로 가리키는 대상은 array1과 다르지만 그 중의 원소와 array1의 원소는 같은 대상을 가리킨다.mArrayCopy1은 자신의 객체를 수정할 수도 있습니다.
    [mArrayCopy1 addObject:@"de"];
    [mArrayCopy1 removeObjectAtIndex:0];

array1과 arrayCopy1은 포인터 복제이고 mArrayCopy1은 대상 복제이며 mArrayCopy1은 기간 내의 요소를 삭제하거나 추가할 수 있습니다.그러나 컨테이너 내의 요소 컨텐트는 포인터로 복사됩니다.
컨테이너의 요소 객체는 항상 포인터 복사라는 것을 알 수 있습니다.원소 대상도 대상 복제가 필요하다면 깊이 복제가 필요하다.

3. 객체 사용자 정의


만약 우리가 정의한 대상이라면, 우리 스스로 NSCopying을 실현해야 한다. NSMutable Copying. 이렇게 하면 copy와mutable Copy를 호출할 수 있다.
@interface MyObj : NSObject<NSCopying,NSMutableCopying>
{
         NSMutableString *name;
         NSString *imutableStr;
         int age;
}
@property (nonatomic, retain) NSMutableString *name;
@property (nonatomic, retain) NSString *imutableStr;
@property (nonatomic) int age;
@end
@implementation MyObj
@synthesize name;
@synthesize age;
@synthesize imutableStr;
- (id)init
{
         if (self = [super init])
         {
                   self.name = [[NSMutableString alloc]init];
                   self.imutableStr = [[NSString alloc]init];
                   age = -1;
         }
         return self;
}
- (void)dealloc
{
         [name release];
         [imutableStr release];
         [super dealloc];
}
- (id)copyWithZone:(NSZone *)zone
{
         MyObj *copy = [[[self class] allocWithZone:zone] init];
         copy->name = [name copy];
         copy->imutableStr = [imutableStr copy];
// copy->name = [name copyWithZone:zone];;
// copy->imutableStr = [name copyWithZone:zone];//
         copy->age = age;
         return copy;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
         MyObj *copy = NSCopyObject(self, 0, zone);
         copy->name = [self.name mutableCopy];
         copy->age = age;
         return copy;
}

요약:


1: 변환할 수 없는 객체의 경우 copy는 모두 얕은 복사, 즉 포인터 복사입니다.mutableCopy는 모두 Alloc의 새 객체로 반환됩니다.2: 가변 객체의 경우 copy 및 mutableCopy 모두 Alloc 새 객체가 반환됩니다.3: 가변적이든 가변적이든 copy가 되돌아오는 대상은 가변적이며,mutableCopy가 되돌아오는 대상은 모두 가변적이다.4: 컨테이너 클래스의 대상, 가변적이든 안 변하든,copy,mutableCopy가 되돌아오는 대상에 포함된 대상의 주소는 이전과 같다. 즉, 컨테이너 내의 대상은 모두 얕은 복사이다.

좋은 웹페이지 즐겨찾기