static 선언

sz L·2023년 3월 28일
2

C++

목록 보기
22/40
post-thumbnail

static

정적변수는 지역변수와 전역변수를 섞어서 보완한 것이다.

지역변수는 변수가 휘발성이 강하다는 단점이 있고

전역변수는 모~든 공간에서 사용이 가능하다는 단점이 있다.

두 변수의 단점을 보완한 변수가 정적변수이다

정적변수는 해당지역에서 사용되며, 데이터가 프로그램이 끝날때까지 남아있다.(지역이 끝나도 소멸되지 않는다)

  • 전역변수에서 선언된 static은 선언된 파일 내에서만 참조를 허용하겠다는 의미
  • 함수 내에 선언된 static은(지역변수에 붙은 static) 한번만 초기화되고, 지역변수와 달리 함수를 빠져나가도 소멸되지 않는다
#include <iostream>
using namespace std;

void Static_Counter()
{
	static int cnt;
	cnt++;
	cout << "Current Static cnt: " << cnt << endl;
}

void Counter()
{
	int cnt = 0;
	cnt++;
	cout << "Current cnt: " << cnt << endl;
}

int main()
{
	for (int i = 0;i < 10;i++) {
		Static_Counter();
		Counter();
	}
	return 0;
}

  • Static_Counter()에서 선언된 static int cnt;
    • 프로그램 실행과 동시에 메모리에 할당, 프로그램이 끝나면 소멸
    • static 변수의 초기화는 1번만 실행
    • 초기화하지 않으면 0으로 초기화 됨
  • Counter() 에서 선언된 int cnt = 0;
    • for문을 통해 함수가 실행 될 때마다 초기화가 일어남

static멤버변수의 초기화 방법

#include <iostream>
using namespace std;

class SoSimple
{
private:
	static int simObjCnt;
public:
	SoSimple()
	{
		simObjCnt++;
		cout << simObjCnt << "번째 SoSimple 객체" << endl;
	}
};
// static 멤버변수는 객체 소속(멤버)이/가 아니라 class 소속이기 때문에 class 밖에서 초기화가 이뤄져야한다.
int SoSimple::simObjCnt = 0; // 클래스 정적변수 초기화 방법

class SoComplex
{
private:
	static int cmxObjCnt;
public:
	SoComplex()
	{
		cmxObjCnt++;
		cout << cmxObjCnt << "번째 SoComplex 객체" << endl;
	}
	SoComplex(SoComplex &copy)
	{
		cmxObjCnt++;
		cout << cmxObjCnt << "번째 SoComplex 객체" << endl;
	}
};
int SoComplex::cmxObjCnt = 0;

int main()
{
	SoSimple sim1;
	SoSimple sim2;
	
	SoComplex com1;
	SoComplex com2 = com1;
	SoComplex();
	
	return 0;
}

  • int SoSimple::simObjCnt = 0;처럼 멤버변수에 static으로 선언된 변수
    • static 멤버변수는 객체 소속이 아니라 클래스 소속이기 때문에 클래스의 밖에서 초기화 해줘야 함

또한 static멤버변수는 객체 소속이 아니라 클래스 소속이기 때문에 클래스를 통한 접근도 가능하다

#include <iostream>
using namespace std;

class SoSimple
{
public:
	static int simObjCnt; // 외부접근 가능
public:
	SoSimple()
	{
		simObjCnt++;
	}
};
int SoSimple::simObjCnt = 0;

int main()
{
	cout << SoSimple::simObjCnt << "번째 SoSimple 객체" << endl; // 클래스 멤버이기 때문에 :: 사용해서도 접근이 가능하다
	SoSimple sim1;
	cout << sim1.simObjCnt << "번째 SoSimple 객체" << endl;
	SoSimple sim2;

	cout << SoSimple::simObjCnt << "번째 SoSimple 객체" << endl;
	cout << sim2.simObjCnt << "번째 SoSimple 객체" << endl;

	return 0;
}

cout << SoSimple::simObjCnt << "번째 SoSimple 객체" << endl;에서 SoSimple::simObjCnt를 통해 static 멤버변수에 접근한 형태


static 멤버함수

static 멤버함수는 static 멤버변수와 특성이 동일함

  • 선언된 클래스의 모든 객체가 공유한다
  • public으로 선언이 되면, 클래스의 이름을 이용해서 호출한다
  • 객체의 멤버로 존재하는 것이 아니다
  • static 멤버함수 내에서는 static 멤버변수와 static 멤버함수만 호출이 가능하다
class SoSimple
{
private:
	int num1;
    static int num2;
public:
	SoSimple(int n) : num1(n)
    { }
    static void Adder(int n)
    {
    	num1 += n;  // 에러발생
        num2 += n;
    }
};
int SoSimple::num2=0;

num1 += n;에서 에러가 발생하는데 이는 static으로 선언되지 않은 멤버변수에 접근해서 발생한 에러이다.
static void Adder(int n)구문이 static으로 객체소속이 아니라 클래스 소속이다.
num1은 객체 소속


mutable

mutable 키워드는 const 함수 내에서의 값의 변경의 예외적으로 허용한다.
사용하는 것 지양

#include <iostream>
using namespace std;

class SoSimple
{
private:
	int num1;
	mutable int num2;
public:
	SoSimple(int n1,int n2) : num1(n1),num2(n2)
	{ }
	void ShowSimpleData() const
	{
		cout << num1 << ", " << num2 << endl;
	}
	void CopyToNum2() const
	{
		num2 = num1;
	}
};

int main()
{
	SoSimple sm(1, 2);
	sm.ShowSimpleData();
	sm.CopyToNum2();
	sm.ShowSimpleData();

	return 0;
}

profile
가랑비는 맞는다 하지만 폭풍은 내 것이야

0개의 댓글