20141008 (C++ 맴버 이니셜라이저)

154일차








----------

C++

----------





------- 맴버 이니셜라이저(Member Initializer)

우선 예제를 보자.


class Point

{

private:

int x;

int y;


public:

Point()

{

cout << "Point 디폴트 생성자 호출" << endl;

x = 0;

y = 0;

}


Point(int x, int y)

{

cout << "Point 생성자 호출" << endl;

Point::x = x;

Point::y = y;

}


~Point()

{

cout << "Point 소멸자 호출" << endl;

}


void Print()

{

cout << "[" << x << ", " << y << "]\n";

}

};


class Rectangle

{

public:

Point upLeft;

Point lowRight;


public:

Rectangle()

{

cout << "Rectangle 디폴트 생성자 호출" << endl;

}


Rectangle(int x1, int y1, int x2, int y2)

:upLeft(x1, y1), lowRight(x2, y2) // 함수의 코드를 실행전 이 코드를 먼저 수행

{

cout << "Rectangle 생성자 호출" << endl;

}


~Rectangle()

{

cout << "Rectangle 소멸자 호출" << endl;

}


void Print()

{

upLeft.Print();

lowRight.Print();

}

};


int main(void)

{

Rectangle obj1;

obj1.Print();


Rectangle obj2(1,2,3,4); // 요놈을 자세히 볼 것.

obj2.Print();


return 0;

}


결과



이렇듯 Rectangle 객체가 생성되기 전에 Point 객체가 먼저 생성되는데


Rectangle(int x1, int y1, int x2, int y2)

:upLeft(x1, y1), lowRight(x2, y2) // 함수의 코드를 실행전 이 코드를 먼저 수행

{

cout << "Rectangle 생성자 호출" << endl;

}


생성자와 중괄호 사이에 저렇게 넣으면 Point 객체가 생성되기 전에 빨강줄 코드부터 수행한다.

이것이 맴버 이니셜라이저이다.




또 이런 경우도 가능하다.

class Rectangle

{

public:

Point upLeft;

Point lowRight;

const int iNum; // const int iNum = 100;  //error


public:

Rectangle()

:iNum(100)

{

cout << "Rectangle 디폴트 생성자 호출" << endl;

// iNum = 100; // error;

}

};





--- C++에서는 변수 초기화에 괄호를 사용하여서도 가능하다.


예)

int iNum2(200);    // int iNum2 = 200;

cout << "iNum2 : " << iNum2 << endl;


int * ip(&iNum2);    // int * ip = &iNum2;

cout << "*ip : " << *ip << endl;


char buf[]("hihihi");    // char buf[] = "hihihi";

cout << "buf : " << buf << endl;


char * pbuf("this is test");    // char * pbuf = "this is rest";

cout << "*pbuf : " << pbuf << endl;


결과










--- 생성자, 소멸자 다른 예제


class Point

{

private:

int x;

int y;


public:

Point()

{

cout << "Point 디폴트 생성자 호출" << endl;

x = 0;

y = 0;

}

~Point()

{

cout << "Point 소멸자 호출" << endl;

}

};


void test(Point obj)

{

80: Point obj1;


82: obj1 = obj;

}


int main()

{

87: Point objA;


89: test(objA);


91: return 0;

}


결과



생성자가 두 번 호출되었고, 소멸자는 3번 호출되었다.

어셈블리로 확인해 본 결과.


_main PROC ; main 함수

; Line 87

lea ecx, DWORD PTR _objA$[ebp]

call ??0Point@@QAE@XZ         ; Point::Point 생성자 호출

mov DWORD PTR __$EHRec$[ebp+8], 0

; Line 89

mov eax, DWORD PTR _objA$[ebp+4]

push eax

mov ecx, DWORD PTR _objA$[ebp]

push ecx

call ?test@@YAXVPoint@@@Z ; test

add esp, 8

; Line 91

mov DWORD PTR $T30281[ebp], 0

mov DWORD PTR __$EHRec$[ebp+8], -1

lea ecx, DWORD PTR _objA$[ebp]

call ??1Point@@QAE@XZ         ; Point::~Point 소멸자 호출

mov eax, DWORD PTR $T30281[ebp]


?test@@YAXVPoint@@@Z PROC ; test 함수

; Line 80

lea ecx, DWORD PTR _obj1$[ebp]

call ??0Point@@QAE@XZ         ; Point::Point 생성자 호출

; Line 82

mov eax, DWORD PTR _obj$[ebp]

mov DWORD PTR _obj1$[ebp], eax

mov ecx, DWORD PTR _obj$[ebp+4]

mov DWORD PTR _obj1$[ebp+4], ecx

; Line 83

lea ecx, DWORD PTR _obj1$[ebp]

call ??1Point@@QAE@XZ         ; Point::~Point 소멸자 호출

mov DWORD PTR __$EHRec$[ebp+8], -1

lea ecx, DWORD PTR _obj$[ebp]

call ??1Point@@QAE@XZ         ; Point::~Point 소멸자 호출


어셈에서 이런 식으로 처리했다.


생성자가 main에서 Point objA를 선언하면서 한 번,

test에서 Point obj1을 선언하면서 한 번 호출하고,


소멸자는 main return 하면서 한 번,

test에서 return하면서 obj1, obj가 소멸되면서 두 번 호출하였다.








설정

트랙백

댓글