관리 메뉴

기억을 위한 기록들

[Fundamental C++] 1. 선언과 정의 본문

C & CPP/Fundamental C++

[Fundamental C++] 1. 선언과 정의

에드윈H 2021. 4. 27. 17:07

정의

해당 객체를 위해 메모리 영역을 확보하는 것

클래스 정의 : 

class CTest
{
public:
   int a;
   int b;
};

선언

어떤 객체가 존재하고 있음을 알리는 역할

class CTest; //선언


CTest myTest;//사용

 

정의는 선언을 포함한다. 어떤 객체를 정의하는 순간 해당 객체는 알려지므로 선언을 따로 해줄 필요가 없다. 그렇다고 선언이 불필요한 것은 아니다.(전방 선언 등)

 

 

 

- 같은 이름의 전역 변수는 실행 공간에 오직 단 한 번만 정의될 수 있다.

//A.cpp 
int g_ValA; //Ok
int g_ValCommon; //Link Error

//B.cpp
int g_ValB; //Ok
int g_ValCommon; //Link Error

- 같은 이름의 정적(static) 변수는 각각의 오브젝트 공간(cpp에 의해 생긴 공간이라 하겠음)에 단 한 번만 정의될 수 있다. 따라서 실행 공간에는 같은 이름의 정적 변수가 여러 번 정의될 수 있는데 각각은 완전히 서로 다른 개별적인 변수다. 

//A.cpp 
static int s_ValCommon; //ok

static int s_ValA; //컴파일 에러
static int s_ValA; //컴파일 에러

//B.cpp
static int s_ValCommon; //ok

 

 

- 같은 이름과 같은 인자 타입을 가진 전역 함수가 오브젝트 공간에 두 개 이상될 경우 링크 에러

//A.cpp 
int DoSomething(int param)  //Link Error
{
   return 32;
}

//B.cpp
int DoSomething(int param) //Link Error
{
   return 32;
}

- 같은 이름, 인자 타입, 반환 타입을 가진 함수는 실행 공간에 2개 이상 정의된 경우 컴파일 에러

//A.cpp 
int DoSomething2(int param)  //컴파일 Error
{
   return 32;
}

float DoSomething2(int param) //컴파일 Error
{
   return 32.0f;
}

- 같은 이름의 클래스는 각각의 오브젝트 공간에 오직 단 한 번만 정의될 수 있다.

//A.cpp 
class CTestA //컴파일 에러
{
public:
    int m_Val;
};

class CTestA //컴파일 에러
{
public:
    int m_Val;
};

- 실행 공간에 같은 이름의 클래스가 여러 번 정의될 수 있지만 만일 구조가 다른 경우 런타임에 문제가 발생시킬 소지가 있다.

//A.cpp 
class CTestA //Ok
{
public:
    int m_Val;
};

//B.cpp 
class CTestA //Ok
{
public:
    int m_Val;
};

 

 

변수 초기값 관련

변수를 정의할 때 0으로 다 해주면 좋지만, 초기화하는데도 CPU를 사용하기 때문이다. 초기화할 변수가 많으면 많을수록 그만큼 효율이 떨어지게 된다.

 

전역 변수가 0으로 초기화되는 이유?

 

- 전역 변수와 정적(static) 변수는 데이터 영역에 위치한다. 이 데이터 영역은 다시 두 부분으로 나뉘게 되는데 초기화된 데이터 영역(Data)과 초기화되지 않은 데이터 영역(BSS/Block Stated Symbol)으로 나누어진다. 

 

-BSS영역이 있는 이유? 초기화되지 않은 전역 변수를 위해 특별히 고안된 것

프로그래밍에서 변수가 생성되는 시점에 초깃값을 가지는 것은 안전을 위해서 필요하다. 지역 변수의 경우 효율을 생각할 때 그렇게 하지 못하는 것뿐이다. 어떤 함수에 지역 변수가 하나 있는데, 그 함수가 1000번 호출되면 해당 지역 변수는 1000번이나 초기화되어야만 한다.

 

- 그에 비해 전역 변수는 프로 세시 시작 시 단 한 번만 초기화하면 되므로 부담이 크지 않다. 하나의 프로젝트에서 전역 변수 개수를 따져도 그리 많지 않다 그래서 전역 변수는 지역변수와 달리 0으로 초기화를 수행한다.

 

- 초기화되지 않은 전역 변수를 가상 메모리 한쪽 영역에 모아놓고 해당 부분만을 0(NULL)으로 채운다면 쉽게 초깃값 0으로 설정할 수 있기 때문이다.

 

- 함수의 반환 값을 받는 정적/전역 변수 또한 BSS영역이다. 반환 값으로 초기화를 하겠지만, 그 시점은 가상 메모리가 모두 구성된 이후 최초의 스레드가 CRT Startup을 수행하고 CRT Startup이 초기화 처리 함수를 호출할 때라서 초기화 처리 함수가 함수를 호출하면서 반환 값으로 초기화하게 된다.

 

- 초기화된 데이터 영역(DATA)과 초기화 되지 않은 데이터 영역(BSS) 주소 차이 확인하기

g_C변수의 주소만 B000이고 다른변수들은 B14*이다.

g_C 변수만 상수로 선언되어 초기화 된 데이터(Data) 영역에 들어가게 되어, 주소 값의 차이가 다른 변수들(BSS영역)과 차이가 꽤 나는 걸 알 수 있다.

 

 

- 정적(static) 변수는 전역 변수의 성질을 그대로 가지면서 접근 범위가 한정되어 있다. 크게 3가지로

1. 소스파일(cpp) 안 - 정적 전역 변수

전역 변수에 static 붙인 것. 해당 소스(cpp) 파일에서만 접근 가능하다는 점 빼곤 일반 전역 변수와 큰 차이가 나지 않는다.

static int gs_Num;

int main()
{
//..
}

2. 클래스 안- 정적 멤버 변수

클래스 멤버 변수에 static 붙인 것. 정적 멤버 변수는 사실상 멤버 변수가 아니다. 즉, 클래스 객체의 영향을 받지 않는다. 클래스 객체가 여러 개 있다고 해서, 정적 멤버 변수는 공유될 수도 있다는 것.  클래스 객체가 점유하는 메모리 영역과는 상관없기 때문.

class A
{
public:
    static int s_Anum;
};

int A::s_Anum = 5 ; //클래스 정적멤버변수 정의

 

3. 함수 안- 정적 지역 변수

지역이라는 단어가 있다고해서 지역변수의 성질을 가지지 않는다. 함수 안에서만 접근할 수 있는 전역 변수와 같다.

함수가 시작할 때 생성되는 것이 아니라 프로세스 시작 시에 생성되고 초기화되어 있는 것. 초기화 과정은 전역 변수 초기화 과정과 일치(DATA, BSS 영역 등), 차이가 하나 있는데 바로 함수의 반환 값 받는 경우이다. 일반 전역 변수는 함수 반환 값으로 초기화하면 0이 들어가 있는데, 정적 지역 변수는 반환 함수가 호출되어 초기화되는 시점이 다르다. 0이 아닌 반환 값을 받고 있는다.

 

 

 

힙 영역의 초기화

일반 지역변수들이 초기화가 자주 일어날 수 있기에, 0으로 초기화되지 않는 것처럼 new나 malloc으로 사용하는 힙의 메모리 또한 지역변수처럼 초기화가 이루어지지 않는다. 빈번하게 할당과 해제가 이루어지기에 기본값을 정해서 초기화될 경우 효율이 떨어진다.

 

 

디버그 변수 초깃값

	int num;

	out << hex << num<< endl;

	int* ptr = new int;
	cout << hex << *ptr << endl;

	cout << hex << *(ptr - 1) << endl;
	cout << hex << *(ptr - 1) << endl;

	delete ptr;
	cout << hex << *ptr << endl;

실행결과

cccccccc //지역변수 
cdcdcdcd //힙 할당 메모리
fdfdfdfd //힙 메모리 양끝
fdfdfdfd //힙 메모리 양끝
feeefeee //해제 된 힙 할당 메모리

'C & CPP > Fundamental C++' 카테고리의 다른 글

[Fundamental C++] 5. 배열  (0) 2021.04.27
[Fundamental C++] 4. 포인터  (0) 2021.04.27
[Fundamental C++] 3. 메모리  (0) 2021.04.27
[Fundamental C++] 2. 빌드  (0) 2021.04.27
쓰기에 앞서  (0) 2021.04.14