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가 소멸되면서 두 번 호출하였다.