달력

10

« 2024/10 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
2010. 5. 11. 20:54

[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 : 재정의 가능




:
Posted by 에너지발전소