질문을 명확히하기 위해 '정적'키워드 사용법을 세 가지 형식으로 분류하려고합니다.
(ㅏ). 변수
(비). 기능
(씨). 클래스의 멤버 변수 / 함수
각 소제목에 대한 설명은 다음과 같습니다.
(A) 변수에 대한 '정적'키워드
이 설명은 조금 까다로울 수 있지만 올바르게 설명하고 이해하면 매우 간단합니다.
이것을 설명하기 위해서는 먼저 변수 의 범위, 지속 시간 및 연결 에 대해 아는 것이 매우 유용 합니다.
1. 범위 : 파일에서 변수에 액세스 할 수있는 위치를 결정합니다. (i) 로컬 또는 블록 범위 의 두 가지 유형이 있습니다 . (ii) 글로벌 범위
2. Duration : 변수가 생성되고 파괴되는시기를 결정합니다. 다시 두 가지 유형이 있습니다. (i) 자동 저장 기간 (로컬 또는 블록 범위가있는 변수의 경우). (ii) 정적 저장 기간 (글로벌 스코프를 갖는 변수 또는 정적 지정자가 있는 로컬 변수 (함수 또는 코드 블록) ).
3. 링크 : 다른 파일에서 변수에 액세스 (또는 링크) 할 수 있는지 여부를 결정합니다. 다시 말하지만 운 좋게도 (i) 내부 연결
(블록 범위 및 전역 범위 / 파일 범위 / 글로벌 네임 스페이스 범위 가있는 변수의 경우 ) (ii) 외부 연결 (전역 범위 / 파일 범위 / 글로벌 네임 스페이스 범위)
일반 전역 및 지역 변수에 대한 이해를 돕기 위해 아래 예를 참조하십시오 (정적 저장 시간을 갖는 지역 변수 없음).
//main file
#include <iostream>
int global_var1; //has global scope
const global_var2(1.618); //has global scope
int main()
{
//these variables are local to the block main.
//they have automatic duration, i.e, they are created when the main() is
// executed and destroyed, when main goes out of scope
int local_var1(23);
const double local_var2(3.14);
{
/* this is yet another block, all variables declared within this block are
have local scope limited within this block. */
// all variables declared within this block too have automatic duration, i.e,
/*they are created at the point of definition within this block,
and destroyed as soon as this block ends */
char block_char1;
int local_var1(32) //NOTE: this has been re-declared within the block,
//it shadows the local_var1 declared outside
std::cout << local_var1 <<"\n"; //prints 32
}//end of block
//local_var1 declared inside goes out of scope
std::cout << local_var1 << "\n"; //prints 23
global_var1 = 29; //global_var1 has been declared outside main (global scope)
std::cout << global_var1 << "\n"; //prints 29
std::cout << global_var2 << "\n"; //prints 1.618
return 0;
} //local_var1, local_var2 go out of scope as main ends
//global_var1, global_var2 go out of scope as the program terminates
//(in this case program ends with end of main, so both local and global
//variable go out of scope together
이제 Linkage의 개념이 온다. 한 파일에 정의 된 전역 변수를 다른 파일에 사용하려는 경우 변수의 연결이 중요한 역할을합니다.
전역 변수의 연결은 키워드 (i) static 및 (ii) extern으로 지정됩니다.
(이제 설명을 얻습니다)
정적 키워드는 지역 및 전역 범위의 변수에 적용 할 수 있으며 두 경우 모두 서로 다른 의미를 갖습니다. 먼저 전역 범위가있는 변수에서 '정적'키워드 사용법 (키워드 'extern'의 사용법을 명확히 함)과 나중에 로컬 범위가있는 사람들에 대한 설명을 설명합니다.
1. 전역 범위를 가진 변수에 대한 정적 키워드
전역 변수는 정적 지속 시간을 가지며, 이는 사용되는 특정 코드 블록 (예 : main ())이 끝날 때 범위를 벗어나지 않음을 의미합니다. 연결에 따라, 선언 된 파일 (정적 전역 변수의 경우) 또는 선언 된 파일 외부 (외부 유형의 전역 변수) 외부의 파일에만 액세스 할 수 있습니다.
extern 지정자를 갖는 글로벌 변수의 경우,이 변수가 초기화 된 파일 외부에서 액세스되는 경우, 함수가 전달되어야하는 것처럼 사용중인 파일에서 전달 선언되어야합니다. 정의가 사용중인 위치와 다른 파일에있는 경우 선언됩니다.
반대로 전역 변수에 static 키워드가 있으면 선언 된 파일 외부에서는 사용할 수 없습니다.
(설명을 위해 아래 예를 참조하십시오)
예 :
//main2.cpp
static int global_var3 = 23; /*static global variable, cannot be
accessed in anyother file */
extern double global_var4 = 71; /*can be accessed outside this file linked to main2.cpp */
int main() { return 0; }
main3.cpp
//main3.cpp
#include <iostream>
int main()
{
extern int gloabl_var4; /*this variable refers to the gloabal_var4
defined in the main2.cpp file */
std::cout << global_var4 << "\n"; //prints 71;
return 0;
}
이제 c ++의 모든 변수는 const 또는 non-const 일 수 있으며 각 'const-ness'에 대해 두 가지 기본 c ++ 연결이 발생합니다 (아무도 지정되지 않은 경우).
(i) 전역 변수가 Const가 아닌 경우 기본적으로 해당 연결은 extern입니다 . 즉 extern 키워드를 사용하여 선언을 통해 다른 .cpp 파일에서 non-const 전역 변수에 액세스 할 수 있습니다 (즉, const가 아닌 전역 변수에는 외부 링크가 있습니다 (정적 지속 시간 포함). 또한 정의 된 원본 파일에서 extern 키워드 사용은 중복됩니다. 이 경우 비 const 전역 변수를 외부 파일에 액세스 할 수 없게하려면 변수 유형 앞에 지정자 'static'을 사용하십시오 .
(ii) 전역 변수가 const 인 경우 기본적으로 연결은 정적입니다 . 즉, const 전역 변수는 정의 된 위치 이외의 파일에서 액세스 할 수 없습니다 (즉, const 전역 변수에는 내부 연결이 있습니다 (정적 지속 시간 포함) 물론이야)). 또한 정적 키워드를 사용하여 const 전역 변수가 다른 파일에서 액세스되는 것을 방지합니다. 여기서 const 전역 변수에 외부 연결을 만들려면 변수 유형 앞에 지정자 'extern'을 사용하십시오.
다음은 다양한 연계가있는 전역 범위 변수에 대한 요약입니다.
//globalVariables1.cpp
// defining uninitialized vairbles
int globalVar1; // uninitialized global variable with external linkage
static int globalVar2; // uninitialized global variable with internal linkage
const int globalVar3; // error, since const variables must be initialized upon declaration
const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
extern const double globalVar5 = 1.57; //this const variable ca be accessed outside the file where it has been declared
다음으로 다른 파일에서 액세스 할 때 위의 전역 변수가 어떻게 작동하는지 조사합니다.
//using_globalVariables1.cpp (eg for the usage of global variables above)
// Forward declaration via extern keyword:
extern int globalVar1; // correct since globalVar1 is not a const or static
extern int globalVar2; //incorrect since globalVar2 has internal linkage
extern const int globalVar4; /* incorrect since globalVar4 has no extern
specifier, limited to internal linkage by
default (static specifier for const variables) */
extern const double globalVar5; /*correct since in the previous file, it
has extern specifier, no need to initialize the
const variable here, since it has already been
legitimately defined perviously */
2. 지역 범위가있는 변수에 대한 정적 키워드
로컬 범위의 변수에 대한 정적 키워드 업데이트 (2019 년 8 월)
이를 두 가지 범주로 세분화 할 수 있습니다.
(i) 함수 블록 내의 변수에 대한 정적 키워드 및 (ii) 명명되지 않은 로컬 블록 내의 변수에 대한 정적 키워드
(i) 펑션 블록 내의 변수에 대한 정적 키워드.
이전, 내가 로컬 범위를 가진 변수는 블록이 입력 될 때 즉, 그들이 존재하는 온, 자동 기간을 언급합니다 (함수 블록 수, 그것을 정상적인 블록 수)와 멸망 할 때 블록의 끝, 긴 이야기의 짧은 변수 로컬 범위에는 자동 지속 시간이 있고 자동 지속 기간 변수 (및 객체)에는 연결이 없으므로 코드 블록 외부에서는 볼 수 없습니다.
경우 정적 지정자 기능 블록 내의 로컬 변수로 도포하고, 그것을 정적 자동에서 변수의 시간 변화 와 수명 시간은 고정 된 메모리 위치를 갖는 수단 프로그램의 전체 기간이고, 그 값은 초기화 cpp 참조에 언급 된대로 프로그램 시작 전에 한 번 (초기화를 할당과 혼동해서는 안 됨)
예를 살펴 보겠습니다.
//localVarDemo1.cpp
int localNextID()
{
int tempID = 1; //tempID created here
return tempID++; //copy of tempID returned and tempID incremented to 2
} //tempID destroyed here, hence value of tempID lost
int newNextID()
{
static int newID = 0;//newID has static duration, with internal linkage
return newID++; //copy of newID returned and newID incremented by 1
} //newID doesn't get destroyed here :-)
int main()
{
int employeeID1 = localNextID(); //employeeID1 = 1
int employeeID2 = localNextID(); // employeeID2 = 1 again (not desired)
int employeeID3 = newNextID(); //employeeID3 = 0;
int employeeID4 = newNextID(); //employeeID4 = 1;
int employeeID5 = newNextID(); //employeeID5 = 2;
return 0;
}
정적 지역 변수와 정적 전역 변수에 대한 위의 기준을 살펴보면 그들 사이의 차이점이 무엇인지 묻고 싶을 수도 있습니다. 전역 변수는 코드 내 어느 시점에서나 액세스 가능하지만 ( const- ness 및 extern- ness 에 따라 다른 변환 단위와 동일 하지만) 함수 블록 내에 정의 된 정적 변수는 직접 액세스 할 수 없습니다. 변수는 함수 값 또는 참조에 의해 반환되어야합니다. 이를 예로 들어 설명해 보겠습니다.
//localVarDemo2.cpp
//static storage duration with global scope
//note this variable can be accessed from outside the file
//in a different compilation unit by using `extern` specifier
//which might not be desirable for certain use case.
static int globalId = 0;
int newNextID()
{
static int newID = 0;//newID has static duration, with internal linkage
return newID++; //copy of newID returned and newID incremented by 1
} //newID doesn't get destroyed here
int main()
{
//since globalId is accessible we use it directly
const int globalEmployee1Id = globalId++; //globalEmployeeId1 = 0;
const int globalEmployee2Id = globalId++; //globalEmployeeId1 = 1;
//const int employeeID1 = newID++; //this will lead to compilation error since newID++ is not accessible direcly.
int employeeID2 = newNextID(); //employeeID3 = 0;
int employeeID2 = newNextID(); //employeeID3 = 1;
return 0;
}
정적 전역 변수와 정적 로컬 변수 선택에 대한 자세한 설명은이 스택 오버 스레드 에서 찾을 수 있습니다
(ii) 명명되지 않은 로컬 블록 내의 변수에 대한 정적 키워드.
로컬 블록이 범위를 벗어나면 로컬 블록 (함수 블록이 아님) 내의 정적 변수에 액세스 할 수 없습니다. 이 규칙에 대한 경고는 없습니다.
//localVarDemo3.cpp
int main()
{
{
const static int static_local_scoped_variable {99};
}//static_local_scoped_variable goes out of scope
//the line below causes compilation error
//do_something is an arbitrary function
do_something(static_local_scoped_variable);
return 0;
}
C ++ 11 constexpr
은 컴파일 타임에 표현식의 평가를 보장하고 컴파일러가 코드를 최적화 할 수 있는 키워드 를 도입했습니다 . 스코프 내의 정적 const 변수의 값이 컴파일 타임에 알려진 경우 코드는와 유사한 방식으로 최적화됩니다 constexpr
. 여기 작은 예가 있습니다
또한 이 stackoverflow 스레드 에서 변수 의 차이 constexpr
와 static const
변수 를 찾아 보는 것이 좋습니다 . 이것으로 변수에 적용된 정적 키워드에 대한 설명을 마칩니다.
B. 기능에 사용되는 '정적'키워드
함수 측면에서 정적 키워드는 간단한 의미를 갖습니다. 여기서는 함수의 링크를 의미합니다.
일반적으로 cpp 파일 내에 선언 된 모든 함수는 기본적으로 외부 링크를 갖습니다. 즉, 한 파일에 정의 된 함수는 정방향 선언으로 다른 cpp 파일에서 사용할 수 있습니다.
함수 선언 전에 static 키워드를 사용하면 internal 로의 연결이 제한됩니다 . 즉, 정의 외부의 파일에서는 정적 함수를 사용할 수 없습니다.
C. Staitc 키워드는 멤버 변수와 클래스 함수에 사용됩니다.
1. 클래스의 멤버 변수에 대한 '정적'키워드
여기 예제로 직접 시작합니다
#include <iostream>
class DesignNumber
{
private:
static int m_designNum; //design number
int m_iteration; // number of iterations performed for the design
public:
DesignNumber() { } //default constructor
int getItrNum() //get the iteration number of design
{
m_iteration = m_designNum++;
return m_iteration;
}
static int m_anyNumber; //public static variable
};
int DesignNumber::m_designNum = 0; // starting with design id = 0
// note : no need of static keyword here
//causes compiler error if static keyword used
int DesignNumber::m_anyNumber = 99; /* initialization of inclass public
static member */
enter code here
int main()
{
DesignNumber firstDesign, secondDesign, thirdDesign;
std::cout << firstDesign.getItrNum() << "\n"; //prints 0
std::cout << secondDesign.getItrNum() << "\n"; //prints 1
std::cout << thirdDesign.getItrNum() << "\n"; //prints 2
std::cout << DesignNumber::m_anyNumber++ << "\n"; /* no object
associated with m_anyNumber */
std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 100
std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 101
return 0;
}
이 예에서 정적 변수 m_designNum은 값을 유지하고이 단일 개인 멤버 변수 (정적이므로)는 객체 유형 DesignNumber의 모든 변수와 공유됩니다.
또한 다른 멤버 변수와 마찬가지로 클래스의 정적 멤버 변수는 클래스 함수와 관련이 없으며 기본 함수에서 anyNumber를 인쇄하여 시연됩니다.
클래스의 const 대 비 const 정적 멤버 변수
(i) 비 const 클래스 정적 멤버 변수
앞의 예제에서 정적 멤버 (공개 및 개인 모두)는 상수가 아니 었습니다. ISO 표준은 비 const 정적 멤버가 클래스에서 초기화되는 것을 금지합니다. 따라서 이전 예와 같이 정적 키워드를 생략해야한다는 경고와 함께 클래스 정의 후에 초기화해야합니다.
(ⅱ) 급의 CONST 정적 멤버 변수
이 간단하고 다른 CONST 멤버 변수 초기화 협약으로 이동이 클래스 즉 CONST 정적 멤버 변수가 될 수 선언 시점에서 초기화되고 이들은 결국 초기화 될 수있다 클래스 정의 후에 초기화 될 때 키워드 const를 정적 멤버에 추가해야한다는 한 가지 경고가있는 클래스 선언
그러나 선언 시점에서 const 정적 멤버 변수를 초기화하는 것이 좋습니다. 이것은 표준 C ++ 규칙을 따르며 코드를 더 깨끗하게 만듭니다.
클래스의 정적 멤버 변수에 대한 자세한 예는 learncpp.com http://www.learncpp.com/cpp-tutorial/811-static-member-variables/ 에서 다음 링크를 찾으십시오
.
2. 클래스의 멤버 함수를위한 '정적'키워드
클래스의 멤버 변수는 정적 일 수 있으므로 클래스의 멤버 함수도 가능합니다. 클래스의 일반 멤버 함수는 항상 클래스 유형의 객체와 연결됩니다. 반대로, 클래스의 정적 멤버 함수는 클래스의 어떤 객체와도 관련이 없습니다. 즉,이 포인터가 없습니다.
둘째, 클래스의 정적 멤버 함수에는 * this 포인터가 없으므로 기본 함수 (ClassName :: functionName ();)에서 클래스 이름 및 범위 분석 연산자를 사용하여 호출 할 수 있습니다.
셋째, 클래스의 정적 멤버 함수는 클래스의 정적 멤버 변수에만 액세스 할 수 있습니다. 클래스의 비 정적 멤버 변수는 클래스 객체에 속해야하기 때문입니다.
클래스의 정적 멤버 함수에 대한 자세한 예는 learncpp.com에서 다음 링크를 찾으십시오.
http://www.learncpp.com/cpp-tutorial/812-static-member-functions/