development

정적 C ++ 클래스 멤버는 언제 초기화됩니까?

big-blog 2020. 12. 5. 10:06
반응형

정적 C ++ 클래스 멤버는 언제 초기화됩니까?


이에 대한 쉬운 대답은없는 것 같지만 정적 클래스 필드에 액세스 할 수있을 때 안전하게 만들 수있는 가정이 있습니까?

편집 : 유일한 안전한 가정은 프로그램이 시작되기 전에 모든 정적이 초기화된다는 것입니다 (를 호출하십시오 main). 따라서 다른 정적 초기화 코드에서 정적을 참조하지 않는 한 걱정할 필요가 없습니까?


표준은 동일한 번역 단위 (일반적으로 .cpp 파일을 의미 함)에 정의 된 객체가 선언이 아닌 정의 순서대로 초기화된다는 두 가지를 보장합니다 .

3.6.2

정적 저장 기간 (basic.stc.static)이있는 객체의 저장소는 다른 초기화가 발생하기 전에 0으로 초기화되어야합니다 (dcl.init). 제로 초기화 및 상수 표현식을 사용한 초기화를 통칭하여 정적 초기화라고합니다. 다른 모든 초기화는 동적 초기화입니다. 정적 저장 기간이 상수 표현식 (expr.const)으로 초기화 된 POD 유형 (basic.types)의 객체는 동적 초기화가 발생하기 전에 초기화되어야합니다. 동일한 번역 단위의 네임 스페이스 범위에 정의되고 동적으로 초기화 된 정적 저장 기간을 가진 객체는 해당 정의가 번역 단위에 나타나는 순서대로 초기화됩니다.

다른 보장 된 점은 번역 단위의 정적 객체 초기화가이 번역 단위의 객체 또는 함수를 사용하기 전에 수행된다는 것입니다.

main의 첫 번째 명령문 이전에 네임 스페이스 범위의 객체에 대한 동적 초기화 (dcl.init, class.static, class.ctor, class.expl.init)가 수행되었는지 여부는 구현에 따라 정의됩니다. 초기화가 main의 첫 번째 문 이후 어느 시점으로 지연되면 초기화 할 객체와 동일한 번역 단위에 정의 된 함수 또는 객체를 처음 사용하기 전에 발생합니다.

내가 보장하는 다른 것은 없습니다 (특히 다른 번역 단위에 정의 된 객체의 초기화 순서가 구현 정의 됨).

편집 Suma의 의견에서 지적했듯이 main입력 하기 전에 초기화되는 것도 보장합니다 .


프로그램이 시작되기 전에 초기화됩니다 (즉, main입력 되기 전에 ).

단일 CPP 파일에 두 개 이상의 정의 (정적 데이터)가있는 경우 파일에 정의 된 순서대로 초기화됩니다 (파일에서 이전 / 위에 정의 된 정의가 다음 파일보다 먼저 초기화 됨). 하나는).

둘 이상의 CPP 파일에 둘 이상의 정의 (정적 데이터)가있는 경우 CPP 파일이 처리되는 순서는 정의되지 않거나 구현에 따라 다릅니다. 이것은 프로그램이 시작되기 전에 호출되는 전역 변수의 생성자가 아직 구성되지 않았을 수있는 다른 CPP 파일에 정의 된 다른 전역 변수를 참조하는 경우 문제가됩니다. 그러나 Meyers의 Effective C ++ 항목 47 ( 글로벌 객체가 사용되기 전에 초기화되었는지 확인 )은 해결 방법을 설명합니다.

  • 헤더 파일에 정적 변수를 정의합니다 (정적이므로 링커가 불평하지 않고도 여러 인스턴스를 가질 수 있음).

  • 해당 변수의 생성자가 필요한 모든 것을 호출하도록합니다 (특히 헤더에 선언 된 전역 싱글 톤 생성).

... 이는 일부 시스템 헤더 파일에서 사용할 수있는 기술이라고 말합니다. 예를 들어 cin정적 변수의 생성자가 사용하기 전에 전역 변수가 초기화 되었는지 확인 합니다.


편집에서 최종 결론이 정확합니다. 그러나 문제는 클래스 자체가 정적입니다. 내 코드에 다른 전역 데이터 / 클래스 정적 멤버를 참조하지 않는 클래스 정적 멤버가 있다고 말하는 것이 더 쉽지만이 경로를 선택하면 곧 문제가 발생할 것입니다. 실제로 클래스 정적 데이터 멤버가 아니라 클래스 정적 래퍼 메서드를 사용하는 것이 유용하다고 찾은 한 가지 접근 방식입니다. 그런 다음 이러한 메서드는 자체적으로 정적 개체를 보유 할 수 있습니다. 예를 들어

TypeX* Class2::getClass1Instance()
{
    static TypeX obj1;
    return &obj1;
}

참고 : 이전 답변은 다음과 같습니다.

다른 보장 된 것은 번역 단위의 정적 객체 초기화가이 번역 단위의 객체 나 함수를 사용하기 전에 수행된다는 것입니다.

이것은 완전히 정확하지 않으며 표준이 여기에서 잘못 추론됩니다. 이것은 main이 입력되기 전에 번역 단위의 함수가 호출되면 참이 아닐 수 있습니다.


실행 중에 언제든지 액세스 할 수 있다고 생각합니다. 정의되지 않은 것은 정적 변수의 초기화 순서입니다.


구현 파일 (.c / cpp / cc) 파일에서 초기화 할 수 있습니다. 컴파일러가 여러 정의에 대해 불평하므로 .h로 초기화하지 마십시오.

일반적으로 main 이전에 초기화되지만 순서는 알 수 없으므로 종속성을 피하십시오. 멤버 함수 내에서 확실히 액세스 할 수 있습니다. 정적 멤버의 경우 초기화 순서를 알 수 없습니다. 멤버가 초기화되었는지 확인하는 정적 함수로 정적 멤버를 캡슐화하는 것이 좋습니다.


이 질문에 대한 완전히 사소한 대답은 아니지만 기본적으로 제어가 프로그램의 진입 점 (메인)으로 전달되기 직전에 초기화됩니다. 초기화되는 순서는 (내가 아는 한) 정의되지 않았으며 컴파일러에 따라 다를 수 있습니다.

편집 : 명확히하기 위해 추가 된 가정이 정확합니다. 주 항목 이후에만 액세스하는 한 초기화시기 / 방법에 대해 걱정할 필요가 없습니다. 그 때 초기화됩니다.


나는 프로세스의 주 스레드가 다음 5 단계를 순서대로 실행할 것이라고 생각합니다.

  1. CRT 라이브러리 초기화

  2. 정적 초기화

  3. main () 함수 실행

  4. 정적 단일화

  5. CRT 라이브러리의 통합

다른 정적 초기화 코드에서 참조 정적을 원하십니까? 다음 코드가 작동 할 수 있습니다.

class A;
static auto_ptr<A> a(auto_ptr<A>(&GetStaticA()));
A &GetStaticA(void)
{
    static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones
    if (a == NULL)
    {
         a = new A();
         return *a;
    }
}

참고 URL : https://stackoverflow.com/questions/1421671/when-are-static-c-class-members-initialized

반응형