-
항목4 : 객체를 사용하기 전에 반드시 그 객체를 초기화하자@ 16. 1 ~ 17. 1/Effective C++ 2013. 8. 25. 21:16
int x;
어떤 상황에서는 x의 값이 확실히 초기화되지만 또 다른 상황에서는 그것이 보장되지 않는다는 것입니다.
어떤 플랫폼의 경우에는 미초기화 객체를 읽기만 해도 프로그램이 서 버리기도 합니다.
가장 좋은 방법은 모든 객체를 사용하기 전에 항상 초기화하는 것이다.
int x =0;
const char *text="welcome to";
double d;
cin >> d; //입력스트림에서 읽음으로써 초기화 수행
이런 부분을 제외하고 나면 c++ 초기화의 나머지 부분은 생성자로 귀결된다.
초기화를 하면서 대입과 초기화를 헷갈리지 않는 것이 가장 중요하다.
생성자에서 초기화는 멤버 초기화 리스트를 사용하는 것이며 그 외의것은 대입이 되고 있는 것이다.
class Rational{ public: Rational(string a, string b){ n=a; d=b; } public: string n, d; };
class Rational{ public: Rational(string a, string b) : n(a), d(b){} public: string n, d; };
위에것은 대입, 아래의 것은 초기화(멤버 초기화 리스트 사용)
데이터 멤버에 사용자가 원하는 값을 주고 시작한다는 점에서는 똑같지만 아래 생성자는 위의 것보다 더 효율적일 가능성이 크다.
대입을 사용한 경우 기본 생성자를 호출해서 초기화를 미리 해놓은 후 에 생성자에서 곧바로 새로운 값을 대입하고 있다.
따라서 먼저 호출된 기본 생성자에서 해 놓은 초기화는 아깝게도 그냥 헛짓이 되고 만다.
반면에 초기화 리스트에 들어가는 인자는 바로 데이터 멤버에 대한 생성자의 인자로 쓰이기 때문이다.
기본 생성자 호출후에 복사 대입연산자를 연달아 호출하는 이전의 방법보다 복사 생성자를 한 번 호출하는 쪽이 더 효율적이다.
기본제공 타입의 객체는 초기화와 대입에 걸리는 비용의 차이가 없다.(int 등)
그러나 멤버 초기화 리스트에 넣어주는 것을 추천한다.
기본제공 타입의 멤버를 초기화 리스트로 넣는 일이 선택이 아니라 의무가 될때도 있다.
상수이거나 참조자로 되어 있는 데이터 멤버의 경우엔 반드시 초기화되어야 한다. 왜냐면 상수와 참조자는 대입 자체가 불가능하기 때문이다.
여기서 잠깐 비지역 정적 객체의 초기화 순서는 개별 번역 단위에서 정해진다.
이게 무슨말이냐면..
별도로 컴파일된 소스 파일이 두개 이상 있으며 각 소스 파일에 비지역 정적 객체가 한 개 이상들어있는 경우에 어떻게 되느냐
그리고 실질적인 문제는 한쪽 번역 단위에 있는 비정적 객체의 초기화가 진행되면서 다른 쪽번역 단위에 있는 비지역 정적객체가 사용되는데 불행히도 다른쪽 번역 단위에 있는 객체가 초기화되어 있지 않을지도 모른다는 점이다.
그 이유는 별개의 번역 단위에서 정의된 비지역 정적 객체들의 초기화 순서는 정해져 있지 않다. 는 것이다.
우선 정적개체란 무엇인가?
자신이 생성된 시점부터 프로그램이 끝날 때까지 살아 있는 객체를 일컫는다.
스택 객체 및 힙 기반객체는 애초부터 정적객체가 될 수 없다는 말이다.
정적객체의 범주에 들어가는 것은
1. 전역객체
2. 네임스페이스 유효범휘에서 정의된 객체
3. 클래스 안에서 static으로 선언된 객체
4. 함수 안에서 static으로 선언된 객체
5. 파일 유효범위에서 static으로 정의된 객체
이들 중에서 함수 안에 있는 정적개체는 지역 정적개체라고 하고 나머지는 비지역 정적 객체라고 한다.
그리고 번역 단위는 기본적으로 소스파일 하나가 된다.
결론 : 비지역 정적 객체를 하나씩 맡는 함수를 준비하고 이 안에 각 객체를 넣는것이다. 함수 속에서도 이들은 정적 객체로 선언하고 그 함수에서는 이들에 대한 참조자를 반환하게 만든다.
비지역 정적 객체가 지역 정적 객체로 변환된것이다.(싱글톤 패턴)
C++에서는 지역 정적 객체는 함수 호출중에 그 객체의 정의에 최초로 닿알을 때 초기화되도록 만들어져있다.
'@ 16. 1 ~ 17. 1 > Effective C++' 카테고리의 다른 글
항목 7:가상 소멸자 (0) 2015.01.14 항목6 : 복사생성자 및 대입연산자 제한 (0) 2015.01.14 항목 37 : 어떤 함수에 대해서도 상속받은 기본 매개변수 값은 절대로 재정의하지 말자 (0) 2014.06.02 항목 33 : 상속된 이름을 숨기는 일은 피하자 (0) 2014.06.01 항목 20 : 값에 의한 전달 보다는 상수객체 참조자에 의한 전달방식을 택하는 편이 낫다 (0) 2013.08.19