C++98 에서는 Member initializer list (콜론 초기화)를 통해서 멤버 변수 초기화 가능하다. 

C++11 부터는 Braced-Init-List를 지원. C++11 이전의 문법에서 멤버 변수의 초기화가 불가능 했다.

클래스의 정의는 실제 메모리에 인스턴스를 생성하는 작업이 아니기 때문이다. 단 static 으로 선한한 멤버 변수는 초기화 가능하다.

 

컨테이너 및 STL에는 std::initializer_list<>로 구현되어 있다.

 

1. 멤버 데이터를 초기화는 3가지 방법

#include <ioostream>
 
class Point {
    int x = 0; // Case 1 : after C++11
    int y = 0;
public:
    Point(int a, int b) : x(a), y(b) {	// Case 2
        x = a;	// Case 3
        y = b;
    }
};
 
int main() {
    Point p(1, 2);
}

1. member field initialization : Can not initialize with the values from Constructor.

2. member initializer list : It's initialization, not assignment.

3. Initilize from inside of Constructor : It's assignment, not initialization.

 

 

#include <iostream>

class Point {
	int x;
    int y;
    
public :
	Point (int a, int b) : x(a), y(b) {}  // Member initializer list
};

int main(){
	Point p(1,2);
    class a = 0; // Initialize first, then call Constructor
    
    class b; // call Constructor
    b=0;	 // assignment
}

멤버 초기화 리스트를 사용하면 생성자 코드를 간단히 나타낼 수 있다. 또한 대입이 아니기기에 효율적으로 초기화가 가능하다. 멤버 이니셜라이져를 통한 초기화는 객체의 생성 이전에 이루어진다.

 

2. 꼭 멤버 초기화 리스트를 사용하는 예

1. 클래스 안에 멤버 데이터가 const 또는 reference로 되어 있을때

#include <iostream>
using namespace std;

class point {
	private :
    	const int temp=0; // Error
        int x;
        int y;
        
	public :
    	point(int _x, int _y) : x(_x), y(_y) {}
        void print() {
        	cout << 'x' << ':' << x << endl;
            cout << 'y' << ':' << y << endl;
        }
};

int main(){
	pint* p = new point(1,3);
    p->print();
}

위 에러가 발생한다면 -std=c++11 compile 옵션으로도 해결가능

#include <iostream>
 
class Point {
    const int conv;
    int& r;
    
public:
    Point(int a, int b) : conv(a), r(b) {
        // conv = a; // If you try assignmet, it'll have an error.
        // r = b;
    }
};
 
int main() {
    Point p(1, 2);
}

 

2. 클래스 안에 디폴트 생성자가 없는 타입이 멤버 데이터로 있을때, 멤버객체변수의 추기

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) {}
};
 
int main() {
    Rect r; // p1 Point Constructor -> p2 Point Constructor -> Rect Constructor
}

 

 

3. 자식 클래스에서 부모 멤버 변수를 초기화 하여 사용하고 싶을 경우

#include <iostream>
using namespace std;

class point {
	private :
		int x;
		int y;
	public :
		void print(){
			cout << x << " " << y << endl;
		}
};

class circle : public point {
	private :
		int num;
	public :
		circle (int _x, int _y) {
			x = _x;
			y = _y;
		}
};

int main(){
	circle a(1,3);
	a.print();
	cout <<sizeof(a)<<endl;
}

부모의 멤버 변수가 private로 선언되었기 때문에 자식 클래스에서 접근이 불가능하다. 자식 객체가 부모 클래스 멤버를 멤버변수명을 통해 접근은 가능하지만, 부모 클래스의 객체가 다로 생성이 되었기 때문에, access control modifier의 영향을 받는다는 의미.

#include <iostream>

using namespace std;

class point {
	private :
		int x;
		int y;
	public :
		point ( int _x, int _y ){
			x=_x;
			y=_y;
		}
		
		void print(){
			cout << x << " " << y << endl;
		}
};

class circle : public point {
	private :
		int num;
	public :
		circle (int _x, int _y) : x(_x), y(_y) {}
};

int main(){
	circle a(1,3);
	a.print();
	cout <<sizeof(a)<<endl;
}

제어 접근자를 private로 그대로 둔다면, 부모 클래스의 생성자를 통해 멤버를 초기화 해야 하는데, 위 방법으로는 디폴트 생성자만 호출되게 된다.

#include <iostream>

using namespace std;

class point {
	private :
		int x;
		int y;
	public :
		point ( int _x, int _y ){
			x=_x;
			y=_y;
		}
		
		void print(){
			cout << x << " " << y << endl;
		}
};

class circle : public point {
	private :
		int num;
	public :
		circle (int _x, int _y) : point(_x,_y){}
};

int main(){
	circle a(1,3);
	a.print();
	cout <<sizeof(a)<<endl;
}

 

3. 주의 사항

#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; 
}

Member initializer list will follow the order of member's definition because it's not assignment.

In the above example, when it's using member initializer list, x will be initialized first.
So, X will have garbage value.

 

 

반응형

'Prog&Algol' 카테고리의 다른 글

C++ | Range-based for loops  (0) 2022.03.20
C++ | auto & decltype for type deduction  (0) 2022.03.20
C++ | using namespace  (0) 2022.03.17
2019 Winter Kakao Internship - Hotel room  (0) 2020.04.14
Day-03. DP와 함께 계단 오르기  (0) 2019.12.14

+ Recent posts