문제

제어 할 수 있습니다 주문 정체되고 파괴?어떤 방법을 적용하는 나의 원하는가?예를 들어 지정하려면 어떤 방법으로는 것처럼 특정 개체 파괴되는 지난,또는 적어도 후 다음과 같은 두 가지 목적입니까?

도움이 되었습니까?

해결책

정적 물체는 역전 순서로 파괴됩니다. 그리고 건축 순서는 제어하기가 매우 어렵습니다. 당신이 확신 할 수있는 유일한 것은 동일한 컴파일 장치에 정의 된 두 개체가 정의 순서대로 구성된다는 것입니다. 다른 것은 다소 무작위입니다.

다른 팁

이것에 대한 다른 대답은 그것이 할 수 없다고 주장합니다. 그리고 사양에 따르면 그들은 옳습니다. 그러나 거기에 ~이다 당신이 그것을 할 수있는 트릭.

a 만 생성하십시오 하나의 정적 변수, 클래스 또는 구조물의 정적 변수를 포함하는 다른 모든 것들이 포함되어 있습니다.

class StaticVariables {
    public:
    StaticVariables(): pvar1(new Var1Type), pvar2(new Var2Type) { };
    ~StaticVariables();

    Var1Type *pvar1;
    Var2Type *pvar2;
};

static StaticVariables svars;

필요한 순서로 변수를 만들 수 있습니다. 파괴하다 당신이 필요로하는 순서대로, 생성자와 소멸자에서 StaticVariables. 이것을 완전히 투명하게 만들려면, 그런 것과 같은 변수에 대한 정적 참조를 만들 수 있습니다.

static Var1Type &var1(*svars.var1);

Voilà- 총 제어. :-) 즉, 이것은 추가적인 작업이며 일반적으로 불필요합니다. 그러나 그것은 ~이다 필수, 그것에 대해 아는 것이 매우 유용합니다.

짧은 대답 : 일반적으로, 아니요.

약간 더 긴 답변 : 단일 번역 단위의 글로벌 정적 개체의 경우 초기화 순서가 위에서 맨 아래에 있으며 파괴 순서는 정확히 반대입니다. 여러 번역 유닛 사이의 순서는 정의되지 않았습니다.

실제로 특정 주문이 필요한 경우 직접이를 수행해야합니다.

정적 객체에 파괴 반대의 순서는 그들이 생성(예:첫 번째 건설체가 파괴되는 지난),그리고 제어할 수 있습니다 순서적 건설을 사용하여 기술에 설명된 항목 47,"는지 확인 글로벌 객체는 초기화되기 전에 그들은 사용 에서"메이어'도서 효과적인 C++.

예를 들어 지정하려면 어떤 방법으로는 것처럼 특정 개체 파괴되는 지난,또는 적어도 다른 정적 onject?

도록 건설하기 전에 다른 정적 객체입니다.

어떻게 제어할 수 있 건설니까?지 모두의 정적에서 동일한 dll.

나는 무시(단순)는 사실 그들이 동일한 DLL.

나의 말씀을 메이어'항목 47(4 페이지)은 다음과 같습니다.가정하면 당신은 글로벌 정의된 헤더 파일에 다음과 같이...

//GlobalA.h
extern GlobalA globalA; //declare a global

...추가 코드가 포함된 파일을 다음과 같이...

//GlobalA.h
extern GlobalA globalA; //declare a global
class InitA
{
  static int refCount;
public:
  InitA();
  ~InitA();
};
static InitA initA;

이것의 효과는 어떤 파일을 포함하는 GlobalA.서(예를 들어,GlobalB.cpp 원본 파일을 정의하는 당신의 두 번째 전역 변수)를 정적의 인스턴스 InitA 클래스로 구성됩니다 전에 다른 것에는 원본 파일(예를들면기 전에 당신의 두 번째 전역 변수).

이 InitA 클래스에는 정전에 참조 카운터입니다.을 때 첫 번째 InitA 인스턴스가 구성되는 지금 보기 GlobalB 인스턴스가 구성되고,InitA 생성자 수있는 무엇이든 할 수 있도록 globalA 인스턴스가 초기화되지 않습니다.

표준 C ++에서는 할 수있는 방법이 없지만 특정 컴파일러 내부에 대한 실무 지식이 적은 경우 달성 할 수 있습니다.

시각적 C ++에서 정적 초기 기능에 대한 포인터는 .CRT$XI 세그먼트 (C 유형 정적 초기) 또는 .CRT$XC 세그먼트 (C ++ 유형 static init의 경우) 링커는 모든 선언을 수집하여 알파벳순으로 병합합니다. 적절한 세그먼트에서 객체를 선언하여 정적 초기화가 발생하는 순서를 제어 할 수 있습니다.

#pragma init_seg

예를 들어, 파일 A의 객체를 파일 B 전에 작성하려는 경우 다음과 같습니다.

파일 A.CPP :

#pragma init_seg(".CRT$XCB")
class A{}A;

파일 b.cpp :

#pragma init_seg(".CRT$XCC")
class B{}B;

.CRT$XCB 이전에 합병됩니다 .CRT$XCC. CRT가 정적 Init 함수 포인터를 통해 반복하면 파일 B 이전 파일이 발생합니다.

Watcom에서 세그먼트는 XI이고 #Pragma 초기화의 변형은 구성을 제어 할 수 있습니다.

#pragma initialize before library
#pragma initialize after library
#pragma initialize before user

... 자세한 내용은 문서를 참조하십시오

아니, 당신은 할 수 없습니다. 정적 물체의 다른 건축/파괴에 의존해서는 안됩니다.

항상 싱글 톤을 사용하여 글로벌 자원의 건축/파괴 순서를 제어 할 수 있습니다.

이전에 초기화하려면 변수가 정말로 필요합니까? main?

그렇지 않은 경우 간단한 관용구를 사용하여 실제로 건축 순서와 파괴 순서를 쉽게 제어 할 수 있습니다. 여기를 참조하십시오.

#include <cassert>

class single {
    static single* instance;

public:
    static single& get_instance() {
        assert(instance != 0);
        return *instance;
    }

    single()
    // :  normal constructor here
    {
        assert(instance == 0);
        instance = this;
    }

    ~single() {
        // normal destructor here
        instance = 0;
    }
};
single* single::instance = 0;

int real_main(int argc, char** argv) {
    //real program here...

    //everywhere you need
    single::get_instance();
    return 0;
}

int main(int argc, char** argv) {
    single a;
    // other classes made with the same pattern
    // since they are auto variables the order of construction
    // and destruction is well defined.
    return real_main(argc, argv);
}

실제로 클래스의 두 번째 인스턴스를 만들려고 시도하는 것은 멈추지 않지만 주장이 실패합니다. 내 경험상 그것은 잘 작동합니다.

a를 사용하여 유사한 기능을 효과적으로 달성 할 수 있습니다 static std::optional<T> 대신 a T. 변수로 수행 한대로 초기화하고 간접적으로 사용하고 할당하여 파괴하십시오. std::nullopt (또는 부스트를 위해 boost::none).

그것은 메모리가 실습된다는 점에서 포인터를 갖는 것과 다릅니다. 이것은 당신이 원하는 것을 생각합니다. 따라서, 당신이 그것을 파괴하고 (아마도 훨씬 나중에) 그것을 재현하면, 당신의 객체는 동일한 주소 (보관할 수 있음)를 가지며 그 당시 동적 할당/거래 비용을 지불하지 않습니다.

사용 boost::optional<T> 당신이 없다면 std:: / std::experimental::.

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