비정적 객체에 대해서.

보물창고·2021년 8월 13일
0

이펙티브 c++

목록 보기
1/6

항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자. - 멤버 초기화 리스트를 사용하자.

반드시 이니셜라이저를 사용하자.
생성자에서 대입하는 방법으로 초기화를 한다면, 생성자 스코프에 들어오기 전에
상속 받거나, 데이터형은 디폴트 생성자호출로 초기화가 이루어진 상태이다.
그런데 스코프 내에서 대입으로 초기화를 한다면 복사대입이 이루어지는 형태이다.
반면에 멤버 초기화리스트를 사용하면 복사생성자 한번의 호출로 2번의 함수 호출을 방지한다.

  • 기본데이터 형인데, 매개변수로 들어오는 값이 관련되지 않더라도 임의적으로
    이니셜라이저로 초기화를 하자.

    -> 매개변수로 들어오지 않았찌만, 멤버 변수는 이니셜라이저로 초기화를 하자!

  • 클래스 내의 멤버 변수는 선언된 순서대로 초기화가 이루어지므로,
    이니셜라이저에서 초기화할때 선언된 순서대로 초기화를 하자.

이니셜라이저를 해야하는 이유

1) 단 한번의 복사생성자 호출로 초기화가 가능하다.
2) 참조변수, 상수변수일경우에는 스코프 내에서 초기화가 불가능하다.

static 변수의 초기화는 언제??

: 전역변수의 static의 경우는 초기화 시점이 언제 이루어지는지 예측할 수 없다.
예를 들어 전역으로 static으로 정의한 클래스 객체가 있고,
생성자에서는 그 객체를 참조한다고 할때,
생성자 호출 전에 반드시 전역 객체가 초기화가 이루어져야 문제가 없으나,
호출 전에 초기화가 반드시 이루어진다는 보장이 없다.
왜냐하면 c++은 파일 단위에서 컴파일이 이루어지는데 초기화 순서가 정해져 있지 않아서이다.

함수에 정의된 static 변수를 지역 정적 객체라고 하는데, 이 친구는 함수의 최초 호출할때 초기화가 이루어진다.
c++에서 보장하는 사실이다.

static 초기화에 대한 예시

느낀점
여태까지 전역변수를 그냥 파일 상단에다가 사용했는데 사용방법을 바꾸자.

  • 추가 240925

  • 초기화는 도대체 언제 되는 걸까?
    : 지금의 경우, empty 이기 때문에 에러 발생한다.

그런데 포인터 아닌 경우, 문제되지는 않는다.



#include <iostream>
#include <string>
#include <vector>

class object
{
private :
	int a;
	double d;
public : 
	object()
		: a{ 1004 }, d{0}
	{}
	int getNum()
	{
		return a;
	}
};

object &callObj()
{
	static object o;
	return o;
}

class wontae
{
public :
	int data;
public :
	wontae()
	{
		data = callObj().getNum();
	}
};


int main()
{
	wontae a;
	std::cout << a.data << std::endl;

	return 0;
}


-> 전역변수로 파일 상단에 위치시키지 말고, 참조자로 반환하는 함수에서
static을 생성하도록 하자.

  • 전연변수는 언제 초기화될지 알 수 없다.
  • 참고로 static은 프로그램 종료될때 해제된다.
profile
🔥🔥🔥

0개의 댓글