[4일차]레퍼런스 카운트 Objective-C2010. 5. 11. 20:54
레퍼런스 카운트
1. 인스턴스의 참조 횟수
2. Objective-C 에서는 인스턴스 관리를 위해 레퍼런스 카운트(레퍼런스 참조횟수)를 저장하고 있는데
alloc을 하는 순간 메모리를 할당하고 카운트 값을 1로 초기화 합니다.
3. retain 메서드는 이 카운트 값을 1 증가 시키고 자기 자신의 id를 리턴합니다.
4. release 메서드는 이 카운트 값을 1 감소 시킵니다.
5. dealloc은 이 참조 카운트 값을 무시하고 무조건 메모리 공간을 해제합니다.
6. objective-C 는 참조 카운트 값이 0인 인스턴스를 해제합니다.
7. retainCount 메서드를 호출하면 그 인스턴스의 참조횟수를 정수로 리턴합니다.
------------------------------------------------------------------------
#import <foundation/foundation.h>
int main()
{
id obj = [[NSObject alloc] init];
NSLog (@"Init : %d\n",[obj retainCount]);
[obj retain];
NSLog (@"retain : %d\n",[obj retainCount]);
[obj retain];
NSLog (@"retain : %d\n",[obj retainCount]);
[obj release];
NSLog (@"release : %d\n",[obj retainCount]);
[obj release];
NSLog (@"release : %d\n",[obj retainCount]);
[obj release];
NSLog (@"release : %d\n",[obj retainCount]);
// retainCount : 0 이므로 가리키고 있는 객체가 없는 상태임. 따라서 런타임 오류가 발생
system("pause");
return 0;
}
------------------------------------------------------------------------
dealloc
dealloc을 호출하는 것은 에러가 아님
retainCount에 상관없이 해제를 하므로 약간 위험할 수 있음
------------------------------------------------------------------------
#import <foundation/foundation.h>
int main()
{
id obj = [[NSObject alloc] init];
NSLog (@"Init : %d\n",[obj retainCount]);
[obj retain];
NSLog (@"retain : %d\n",[obj retainCount]);
[obj dealloc];
NSLog (@"dealloc : %d\n",[obj retainCount]);
// retainCount 런타임 오류가 발생하면 메모리 할당이 되어 있지 않다는것을 확인 할 수 있음
system("pause");
return 0;
}
------------------------------------------------------------------------
그러나 무턱대고 dealloc를 호출하면 위험함..
가령 위의 구문을 복사할 경우 문제가 발생
------------------------------------------------------------------------
#import <foundation/foundation.h>
int main()
{
id obj = [[NSObject alloc] init];
NSLog (@"Init : %d\n",[obj retainCount]);
[obj retain];
NSLog (@"retain : %d\n",[obj retainCount]);
// id obj1 = obj;
id obj1 = [obj retain]; // <= retainCount 증가를 통해 잘못된 메모리 해제를 방어
if ([obj retainCount]==1)
{
[obj dealloc];
}
// [obj dealloc];
NSLog (@"dealloc : %d\n",[obj1 retainCount]);
// 참조복사를 한 경우 참조가 삭제되어 문제가 발생
// c#의 경우 참조가 걸려 있으면 dealloc을 할 수 없음.
// release 도 동일한 문제가 발생할 수 있으므로 retain 을 확인해야 함.
// retain은복사를 하거나 매개변수로 사용되었다는것을 알려주기위해 만들어짐.
// 인스턴스가 매개변수로 사용될때 고민해야 함.
// 함수생성시 매개변수에 포인터를 쓰는것은 위험한 발상이다.(중간에 하나만 끊겨도 많은 문제가 야기된다)
// 멤버가 public 라면 init 생성시 매개변수로
// @interface Test
// -(id) init : (Test*) x
// { self = x }
// [[Test alloc] init:x];
system("pause");
return 0;
}
------------------------------------------------------------------------
안전하게 복사하는 방법
// int a=10;
// int *p = (int*) malloc(4);
// *p = a;
// free(p);
dealloc은 재정의 가능
1. 반드시 super dealloc을 호출해야 하고 release를 이용해서 사용하는것이 바람직하고 일반적으로 정리작업에 사용
------------------------------------------------------------------------
#import <foundation/foundation.h>
@interface Test : NSObject
{
@public
int a;
}
-(id)init :(Test*)obj;
@end
@implementation Test
-(id)init:(Test*)obj
{
self = [super init];
if(self !=nil)
{
self->a = obj->a;
}
return self;
}
@end
Test obj=[Test alloc];
Test obj1=[[Test alloc]init:obj];
------------------------------------------------------------------------
NSString 상수
1. @"문자열"
2. 프로그램 종료시까지 해제되지 않는 인스턴스임.
3. retain, release 무시
4. retainCount 는 양의정수 최대값에서 불변입니다.
const
1. 변수를 상수화시켜주는 예약어
2. C 에서와 거의 동일하게 사용되지만 멤버로 선언하지 않는다는점이 다름.
3. # define과도 유사하지만 #define은 컴파일시 이미 변경이 된다는 점이 다름.
4. 클래스 구현부에서 선언하자마자 초기화하면 전역변수처럼 사용됨.
* 일반 value형 변수에 사용되면 값을 변경할 수 없음. => * 안들어가는 id를 제외한 자료형
* 포인터변수에 사용되면 주소(id)는 변경할 수 있지만 가리키는 데이터는 변경할 수 없다.
5. 인스턴스(멤버) 변수에 const를 지정하면 0으로 사용 - 초기화를 수행하고 난후 변경할 수 없음
------------------------------------------------------------------------
#import <foundation/foundation.h>
@interface Test : NSObject
{
int a;
const int b;
}
-(int)a;
-(int)b;
-(void)setA:(int)n;
-(void)setB:(int)n;
@end
@implementation Test
-(int)a {return a;}
-(void)setA:(int)n
{
a=n;
}
-(int)b {return b;}
-(void)setB:(int)n
{
// b=n; // read-only member err
}
@end
int main()
{
Test * obj= [[Test alloc]init]; // id를 리턴
NSLog(@"%d",[obj a]);
[obj setA:20];
NSLog(@"%d",[obj b]);
[obj setB:20];
NSLog(@"%d",[obj b]);
system("pause");
return 0;
// int a=10;
// const int c=10;
// NSLog(@"%d",a);
// NSLog(@"%d",c);
// a=11;
// c=11; // readonly , error
// return 0 ;
}
자료명이름 * 변수명; <-포인터변수 정의
alloc
메모리를 할당하고 모든 멤버변수를 0로 초기화
initialize :
init : 재정의 가능