문제

변수가 다음과 같이 선언 된 경우 static 함수의 범위에서는 한 번만 초기화되며 함수 호출간에 값을 유지합니다. 평생은 정확히 무엇입니까? 생성자와 소멸자는 언제 호출됩니까?

void foo() 
{ 
    static string plonk = "When will I die?";
}
도움이 되었습니까?

해결책

기능의 수명 static 변수가 처음 시작됩니다[0] 프로그램 흐름은 선언을 만나고 프로그램 종료시 종료됩니다. 이는 실제로 런타임이 실제로 구성된 경우에만 파괴하기 위해 일부 도서 유지를 수행해야 함을 의미합니다.

또한 표준에 따르면 정적 물체의 파괴자는 건설 완료의 역 순서로 실행되어야한다고 말하면[1], 건설 순서는 특정 프로그램 실행에 따라 달라질 수 있으며, 건설 순서는 고려해야합니다.

예시

struct emitter {
    string str;
    emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
    ~emitter() { cout << "Destroyed " << str << endl; }
};

void foo(bool skip_first) 
{
    if (!skip_first)
        static emitter a("in if");
    static emitter b("in foo");
}

int main(int argc, char*[])
{
    foo(argc != 2);
    if (argc == 3)
        foo(false);
}

산출:

C :> Sample.exe
Foo에서 만들어졌습니다
Foo에서 파괴

C :> Sample.exe 1
IF에서 만들어졌습니다
Foo에서 만들어졌습니다
Foo에서 파괴
IF에서 파괴되었습니다

C :> Sample.exe 1 2
Foo에서 만들어졌습니다
IF에서 만들어졌습니다
IF에서 파괴되었습니다
Foo에서 파괴

[0] 부터 C ++ 98[2] 다중 스레드에 대한 언급이 없음 다중 스레드 환경에서 어떻게 행동 할 것인지 지정되지 않으며 다음과 같이 문제가 될 수 있습니다. 로디 언급.

[1] C ++ 98 부분 3.6.3.1 BASIC.START.TERT

[2] C ++ 11에서 정적은 스레드 안전 방식으로 초기화되며, 이는 다음으로도 알려져 있습니다. 마법 정적.

다른 팁

Motti는 주문에 대해 옳지 만 고려해야 할 다른 것들이 있습니다.

컴파일러는 일반적으로 숨겨진 플래그 변수를 사용하여 로컬 정적이 이미 초기화되었는지 여부를 나타냅니다.이 플래그는 함수에 대한 모든 항목에서 확인됩니다. 분명히 이것은 소규모 성능 히트이지만, 더 큰 관심사는이 깃발이 스레드 안전을 보장하지 않는다는 것입니다.

위와 같이 로컬 정적이있는 경우 foo 여러 스레드에서 호출되며 인종 조건이 발생할 수 있습니다. plonk 잘못 또는 여러 번 초기화됩니다. 또한이 경우 plonk 그것을 구성한 것과는 다른 실에 의해 파괴 될 수 있습니다.

표준의 말에도 불구하고, 나는 현지 정적 파괴의 실제 순서에 매우주의를 기울일 것입니다. 왜냐하면 당신이 파괴 된 후에도 여전히 유효한 정적에 의존 할 수 있기 때문에, 이는 실제로 추적하기가 어렵 기 때문입니다.

기존 설명은 표준의 실제 규칙 없이는 실제로 완료되지 않습니다. 6.7에서 찾을 수 있습니다.

정적 저장 시간 또는 스레드 저장 시간을 갖는 모든 블록 스코프 변수의 초기화는 다른 초기화가 이루어지기 전에 수행됩니다. 정적 저장 시간을 갖는 블록 스코프 엔티티의 일정한 초기화는 해당되는 경우 블록이 처음 입력되기 전에 수행됩니다. 구현은 구현이 네임 스페이스 범위에서 정적 또는 스레드 저장 시간과 함께 변수를 정적으로 초기화하는 것과 동일한 조건에서 정적 또는 스레드 스토리지 지속 시간을 갖는 다른 블록 스코프 변수의 초기 초기화를 수행 할 수 있습니다. 그렇지 않으면 그러한 변수는 제어가 처음으로 선언을 통과 할 때 초기화됩니다. 이러한 변수는 초기화가 완료되면 초기화 된 것으로 간주됩니다. 초기화가 예외를 던지면 종료되면 초기화가 완료되지 않으므로 다음에 제어가 선언에 들어가면 다시 시도됩니다. 변수가 초기화되는 동안 제어가 선언에 동시에 들어가는 경우, 동시 실행은 초기화 완료를 기다려야한다. 제어가 변수가 초기화되는 동안 선언을 재귀 적으로 재 입력하면 동작이 정의되지 않습니다.

FWIW, CodeGear C ++ Builder는 표준에 따라 예상 순서로 파괴되지 않습니다.

C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if

... 이것은 파괴 질서에 의존하지 않는 또 다른 이유입니다!

그만큼 정적 변수 일단 플레이에 나옵니다 프로그램 실행이 시작됩니다 프로그램 실행이 끝날 때까지 사용할 수 있습니다.

정적 변수는 메모리의 데이터 세그먼트.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top