잡담소장소

기밀태씨 강의 본문

Study ;3

기밀태씨 강의

알 수 없는 사용자 2012. 6. 5. 11:37

 

 

1. 포인터의 기본.

 

#include <stdio.h>

typedef struct _IntStruct
{
int val;
} IntStruct;

void changeValue(int *a)
{
*a = 10; //받은 주소값에 해당하는 저장된 값을 변경
}

void changeStruct(IntStruct *s)
{
s->val = 20; //받아온 포인터를 이용한 값 변경
}

void makeStruct(IntStruct **s) //포인터의 주소값의 주소값을 가져옴
{
IntStruct* tmp;
tmp = (IntStruct*) malloc(sizeof(IntStruct)); 
tmp->val = 30;
*s = tmp;  //주소값의 주소값을 바꿈 ( 아무런 값이 없는 10001번 주소의 struct를 val이 30인 10002번 주소의 struct로 덮어 씌움
}

int main()
{
int a;
IntStruct* b;
IntStruct* c;

a = 0;
changeValue(&a); // 주소값 넘김
printf("%d\n", a);

b = (IntStruct*) malloc(sizeof(IntStruct));
b-> val = 0;
changeStruct(b); //포인터 자체를 넘김
printf("%d\n", b->val);

makeStruct(&c); //포인터의 주소값을 넘김
printf("%d\n", c->val);
free(c);

return ;
}

 

2. object c에서의 객체 생성과 소멸

 

생성자: 클래스 객체를 생성하고 초기화하는 메소드

소멸자: 메모리가 할당된 객체의 메모리를 회수

 

이하 네이트온 대화 발췌 (-_-;;)

 

우리는 C의 포인터와 malloc을 배웠어요
malloc은 보통 구조체에 사용할 메모리를 할당하는데 쓰지요
C++에서는 클래스와 객체가 도입되었는데
사실 C++에서 클래스와 구조체는 완전히 똑같습니다.
대신 다른 점은
C에서 할 수 없었던
private, public같은 access modifier와
그리고 구조체에 고유의 함수를 정의할 수 있다는 점이죠

 

자 그럼 C의 구조체와 C++의 구조체의 차이를 알아봤으니
둘 사이의 생성 방식도 다르다는 것과
어떻게 생성하는지 원리를 볼까요
C에서는 구조체를 malloc을 이용해서 보통 생성하죠?
근데 여기에는 귀찮은 점이 있어요.
malloc은 메모리를 할당만 하지
그 안에 값을 어떻게 해야 할지는 전혀 상관하지 않아요

 

그래서
구조체에 int가 선언되었다면
그 안에 값이 0일 거라고 생각하면 매우 오산이예요
메모리에 무슨 값이 들어있을지 모르니까
그러니까 구조체를 쓰려면 원래
처음에 메모리를 할당 받아서 그 안에
무슨 값이 초기값으로 들어가 있을지를
써주어야 해요.
그래서 C++을 만든 훌륭한 사람들은
생성자 라는것을 고안해 냈지요
생성자란 객체에 메모리가 할당되면
어떤 함수가 반드시 호출 되도록 만든거예요
그래서 사실 생성자는 두가지 일을 해요
1. 객체가 생성될 수 있도록 메모리를 할당합니다.
2. 생성자 함수를 호출해서 객체를 초기화하게 해줍니다.
여기까지 오케이?
 
이건 우리가 잘 아는 php도 똑같아요.

 

$a = new Ponyang();
C++의 문법도 똑같아요
Ponyang a = new Ponyang();
이러면 new 명령어가 하는 일은 내부적으로,
아 Ponyang* a 가 되겠네요
내부적으로는
a = (Ponyang*)malloc(sizeof(Ponyang));
a->Ponyang();
이렇게 됩니다. 이해 됐나요?
여기서 a->Ponyang()은 Ponyang의 생성자 함수예요.
 
이건 객체를 사용하는 거의 모든 언어가 똑같아요
자 그럼 이제 우리는
원래 우리가 배우려고 했던 ObjC를 살펴보겠어요.
현대의 거의 모든 프로그래밍 언어의 문법은
C++과 스타일이 거의 유사하지만,
ObjC는 C++과 동시대의 언어지만, C++과는 다른 사람들이
만든 언어예요. 그래서 문법에 상당한 차이가 있어요.
ObjC는 대괄호를 사용해서 객체를 만들거나, 호출합니다.
일단 ObjC에서 뽀냥 클래스를 만들때는 이렇게 해요.
Ponyang* a = [[Ponyang alloc] init];
이 라인을 살펴보면,
맨 처음 실행되는 것은 [Ponyang alloc] 이예요.

 

ObjC의 모든 클래스는 NSObject라는 클래스를 상속하는데,
alloc은 static method로 여기에 정의되어 있어요
alloc은 C에서 우리가 봤던 malloc과 똑같은 일을 합니다.
C스타일로 써보자면,
malloc(sizeof(Ponyang)) 과 같은 문장이지요.
그럼 이제 객체를 초기화해야겠죠?
이건 init을 사용해요.
그래서
저 문장을 풀어서 쓰면
Ponyang* a = [Ponyang alloc];
a = [a init];
이렇게 되는 것이예요.
왜냐면 C++이 생성자를 도입할 때,
ObjC는 생성자 대신 2단계 초기화를 하는 방법을
사용했기 때문이죠.
좀더 명시적이라고 할 수 있어요.
그리고 init은 반드시 init이라고 쓰지 않고,
다른 이름을 사용해도 무방해요. 저건 일종의 관례예요.
오케이?
 
(나)
init 는
예약어가 아닌
Ponyang 클래스의
생성자 함수라는겁니까..
 
그렇죠 그냥 일반 함수예요.
훌륭하군요
 
그래서
init에 추가적으로 파라미터를 주고 싶을 때에는
아예 이름이 달라집니다.
ObjC만의 스타일인데,
Ponyang* a = [[Ponyang alloc] initWithLover: iltae];
이렇식으로 사용해요.
초기화 함수의 이름이 initWithLover로 바뀌었죠

 

파라미터가
많아지면
모든 파라미터에 각각 저렇게
시그니처가 붙어서
호출이 길어져요.
예를 들면
[[Ponyang alloc] initWithLover:iltae andSister: jihyun];
이런식으로 돼요

 

얼핏 보면 뭔가 싶지만
파라미터 정의를 매우 서술적으로 하는게
ObjC의 특징이죠
저 init은 파라미터가 두개예요.
얼핏 보면 뭔가 싶지만
파라미터 정의를 매우 서술적으로 하는게
ObjC의 특징이죠
저 init은 파라미터가 두개예요.
 
(나)
함수명은요..?
 
initWithLover : iltae
andSister : jihyun
함수명은 initWithLover andSister가 되죠
ㅋㅋ
funny한 언어죠? ㅋㅋ

 

이 방식은 간결한 C의 방식보다는
최초의 객체지향 언어인 smalltalk의 방식을 계승한 것이예요.
어쨌던 익숙해지면
타이핑이 많아지는 대신 함수 이름과 파라미터를 알아보긴 쉬워요

 

자 그리고
이제 공포의 시간
소멸자를 알아볼 시간입니다.
C에서는
malloc을 하면 반드시 free를 해야 되지요?
C++에서는 new의 짝꿍인 delete가 있어요.
Ponyang* a = new Ponyang();
을 했다면
반드시
delete a;
를 해서
메모리를 해제해 줘야 해요.
free(a)와 똑같은 방식이지만,

 

소멸자 함수가 호출된다는게 달라요
C++에서 생성자는 클래스 이름과 똑같고,
소멸자는 클래스 이름 앞에 ~가 붙어요.
Ponyang->Ponyang이라는 함수는 생성자
Ponyang->~Ponyang이라는 함수는 소멸자
자 그럼
여긴 어렵지 않아요.
malloc / free를 똑같이 계승하고 확장한 거니까.
Objective C에서는 그럼 어떨까요
Objective C에서는 생성과 초기화를 따로 하지요
그래서
초기화의 짝은 없어요.
대신 객체가 완전히 메모리에서 내려갈 때는
메모리를 할당하는 alloc의 짝인
dealloc이 호출돼요

 

하지만 개발자는 이걸 건드릴 필요가 대부분 없어요.
그래서 당분간 소멸자는 잊긔
있을 때도 있어요. 하지만 일단 잊긔
왜냐면 복잡해.
그거보다 먼저 해야 할 일은
레퍼런스(참조) 카운터예요.
전에 얘기했다시피, malloc을 하면 반드시 free를 해줘야 해요
new를 하면 반드시 delete를 해줘야 하고.
근데
Ponyang* a = new Ponyang();
Ponyang* b = a;
라고 해서
두개의 변수를 쓰고 있었어요.
근데 누가
delete a; 라고 해버렸어요
그럼 어떻게 될까요
b 변수를 가지고 뭔가를 하려고 하면
액세스 위반이 어쩌구 하는 팝업과 함께
프로그램이 강제종료 될거예요.
왜냐면 Ponyang객체는 메모리에서 삭제되었기 때문이죠.
그리고
delete를 까먹어도 문제예요.

 

그 객체가 메모리를 계속 점유하고 있으니까.
그래서 이 메모리 문제를 해결하는 방법이
크게 가비지 컬렉터와 참조 카운팅인데.
개발자가 알아야 할 것은 참조 카운팅이예요.
참조 카운팅은 뭐냐면.
객체를 쓰고 싶은 사람은 나 이거 쓸래~ 하고
참조 카운트에 +1을 하고
그만 쓰고 싶은 사람은
나 이거 그만 쓸래~ 하고 참조 카운트에 -1을 해요

 

그러다가 참조 카운트가 0이 되면
더이상 아무도 이 객체를 원하지 않는거죠?
그럼 객체가 메모리에서 삭제돼요.
참조 카운트는 C++에서는 boost라는 라이브러리로 제공되고,
ObjC에서는 아까 alloc을 했죠?
ObjC에서는 기본적으로 참조 카운팅을 하게 되어 있어요.

 

객체를 만드는 사람이 [Ponyang alloc]을 하면
Ponyang* a = [Ponyang alloc];을 하면
a의 참조 카운트는 1이 됩니다.
그리고 그만 쓰고 싶으면
[a release] 라는 명령을 써요.
그럼 참조 카운트가 하나 줄어들어요. 그럼 0이 되겠죠?
그럼 객체는 폭ㅋ파ㅋ
release 메소드가 하는 일은
참조 카운트를 -1 한 다음에 0이 되었으면
dealloc을 불러서 객체를 폭파하는 거예요

 

여기까지 알겠나요?
자 그럼 같이 a를 쓰고 싶은 사람은
어떻게 하느냐
Ponyang* a = [[Ponyang alloc] init];
Ponyang* b = a;
이렇게 하면
두개의 변수가 하나의 객체를 보게 되죠?
그럼 이 객체를 쓰고 싶어한 다른 변수에
[b retain]을 하면 돼요.
retain함수는 참조 카운트에 +1을 하는 함수예요.
자 그럼 a와 b에 할당된 객체는
release를 두번 해야만 메모리에서 없어져요.
하나의 객체를 여러 사람이 쓸 때,
객체를 관리하는 책임을 각자 가져갈 수 있는 것이지요.
이게 참조 카운팅의 기본 설계예요.
 
(나)
그럼 b 는 독립된 객체가 되나영
 
아니예요.
같은 객체를 공유하지만,
 
(나)
그저 release 할때
삭제되는걸 막는건가요
 
그렇지요
똘똘이같으니!
여기까지 이해가 됐나요?

 

자 그럼... 마지막으로
Objective C의 진짜 핵심인
autorelease를 배울 차례예요.
전에
C를 할 때 객체를 만들어서 리턴하는 함수를 봤어요
 
우리도 PHP를 할 때
$a = new stdClass;
return $a;
이런거 많이 하죠?
C++에서도 똑같이 할 수 있어요.
근데 문제는
어떤 함수가 객체를 리턴했을 때
이걸 누가 해제하느냐예요
이거 얘기가 너무 많이 갔다.
여기까지만 하고

 

 

 

code 태그를 쓰고싶은데 왜 못쓰는가..

tistory는 제공해달라 ㅠㅠ 해달라 ㅠㅠ

 

 

반응형

'Study ;3' 카테고리의 다른 글

What is Node.js ?  (0) 2012.12.04
SyntaxHighlighter Test  (0) 2012.07.20
리마인드용 개발 이야기  (0) 2012.05.08
프로시저 isqlplus에서 실행하는 방법  (0) 2012.04.18
javascript의 이런 저런  (0) 2012.04.17
Comments