멤버 초기화 리스트 (member initializer lists)
생성자 괄호 ( ) 뒤에 콜론 (:) 을 표기하고 멤버를 초기화 하는 것
Point( int a, int b) : x(a), y(b) { }
대입 방식이 아닌 초기화 방식이다.
멤버 초기화 리스트를 사용하는 방향이 성능면에서 더 좋다.
클래스 선언부 구현부가 분리되어 있을 때, 초기화 리스트는 구현부에 작성한다.
#include <iostream>
class Point
{
int x;
int y;
public:
Point( int a, int b) : x(a), y(b) // 초기화
{
// x = a; // 대입
// y = b;
}
};
int main()
{
Point p(1, 2);
int a = 0; // 초기화. 생성자 호출
int b; // 생성자 호출
b = 0; // 대입. 대입연산자 호출
}
반드시 멤버 초기화 리스트를 사용해야 하는 경우
- 클래스 안에 멤버 데이터가 const 또는 reference 로 되어 있을 때
#include <iostream>
class Point
{
int x;
int y;
const int cval; // const 변수
int& r;
public:
Point( int a, int b, int c) : x(a), y(b), cval(c), r(a)
{
// cval = c; // 대입 : 에러 발생한다.
// x = a;
// y = b;
}
};
int main()
{
Point p(1, 2, 10);
}
- 클래스 안에 디폴트 생성자가 없는 타입이 멤버 데이터로 있을 때 반드시 멤버 초기화 리스트를 사용해야 한다.
Point 의 경우 Point() 생성자가 없기 때문에 Rect(a,b,c,d)가 불렸을 때 p1, p2 멤버 초기화가 바로 되도록 아래 방식의 코딩이 되어야 한다.
class Point
{
int x;
int y;
public:
Point( int a, int b) : x(a), y(b) {}
};
class Rect
{
Point p1;
Point p2;
public:
Rect(int a, int b, int c, int d) : p1(a,b), p2(c,d) // 무조건 이런 초기화가 좋다.
{
// if, switch와 같은 제어문에 의한 값 셋팅이 필요하다면 이곳에 초기화 해줘야함.
//p1(a, b);
}
};
int main()
{
Rect r (1,2,3,4);
// p1 Point 생성자
// p2 Point 생성자
// Rect 생성자
}
주의사항:
초기화 순서는 멤버 데이타가 놓인 순서대로 초기화 된다.
즉, x가 먼저 초기화 되고, y 가 초기화 된다.
Pint() : y(0), x(y) 에서 y(0)가 먼저 수행되지 않는다. int x가 더 먼저 나와서 x가 먼저 초기화 된다.
#include <iostream>
class Point
{
public:
int x;
int y;
public:
Point() : y(0), x(y) // 잘못된 코딩이다!!!
{
}
};
int main()
{
Point p;
std::cout << p.x << std::endl; // 0 ??? 컴파일러에 따라 주소값이 나올 수도 있다.
}
컴파일러마다 처리 방식이 달라서 주의해야 한다.
여기서 사용된 컴파일러는 문제없이 수행하여 0를 출력하고 있으나 조심해야 하는 부분이다.
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/032.gif)
'C++' 카테고리의 다른 글
[C++] 복사 생성자 (copy constructor), 얕은 복사 (Shallow Copy), 깊은 복사 (deep copy) (0) | 2021.08.21 |
---|---|
[C++] Explicit 생성자 (0) | 2021.08.20 |
[C++] 생성자, 소멸자, 위임 생성자, default 생성자 (0) | 2021.08.19 |
[C++] 객체지향 : 접근지정자 private, public, friend (0) | 2021.08.18 |
[C++] STL : stack, vector (0) | 2021.08.17 |
댓글