QGlobalStatic Struct

template <typename Holder> struct QGlobalStatic

QGlobalStatic 클래스는 전역 정적 객체를 구현하는 데 사용됩니다. 더 보기...

Header: #include <QGlobalStatic>
CMake: find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmake: QT += core

참고: 이 구조체의 모든 함수는 스레드 안전합니다.

공용 형

공용 함수

bool exists() const
bool isDestroyed() const
QGlobalStatic<Holder>::Type *operator QGlobalStatic<Holder>::Type *()
QGlobalStatic<Holder>::Type &operator*()
QGlobalStatic<Holder>::Type *operator->()

매크로

Q_GLOBAL_STATIC(Type, VariableName, ...)

상세 설명

QGlobalStatic 클래스는 Q_GLOBAL_STATIC()를 사용할 때 내보내는 프런트엔드 API입니다. 매크로의 사용 시기와 요구 사항에 대한 자세한 내용은 매크로 설명서를 참조하세요.

일반적으로 이 클래스를 직접 사용하지 않고 다음과 같이 Q_GLOBAL_STATIC() 또는 Q_GLOBAL_STATIC_WITH_ARGS() 매크로를 사용합니다:

Q_GLOBAL_STATIC(MyType, myGlobal)

위의 예는 myGlobal 라는 QGlobalStatic 유형의 객체를 생성합니다. 위의 선언 이후 myGlobal 객체는 포인터처럼 사용할 수 있으며, 정확히 한 번만 초기화되도록 보장됩니다. 이 객체는 포인터로 사용하는 것 외에도 exists() 및 isDestroyed()라는 두 가지 메서드를 제공하여 전역의 현재 상태를 확인할 수 있습니다.

Q_GLOBAL_STATIC() 및 Q_GLOBAL_STATIC_WITH_ARGS()도 참조하세요 .

멤버 유형 문서

[alias] QGlobalStatic::Type

이 유형은 Q_GLOBAL_STATIC() 또는 Q_GLOBAL_STATIC_WITH_ARGS() 매크로에 전달되는 Type 매개변수와 동일합니다. 일부 함수의 반환 유형에 사용됩니다.

멤버 함수 문서

[noexcept] bool QGlobalStatic::exists() const

이 함수는 전역 정적 객체가 이미 초기화를 완료하고(즉, 해당 유형의 생성자가 이미 반환된 경우) 아직 소멸을 완료하지 않은 경우 true 을 반환합니다. 특히 이 함수는 초기화가 아직 진행 중인 경우 false 을 반환한다는 점에 유의하세요.

이 함수가 한 번 참을 반환하면 전역 정적 객체가 소멸될 때까지 다시는 거짓을 반환하지 않습니다. 후자는 프로그램 종료 시 또는 전역 정적 객체가 포함된 플러그인이나 라이브러리가 언로드될 때 발생합니다.

이 함수는 프로그램 실행 중 언제든 호출해도 안전하며, 실패할 수도 없고 교착 상태를 유발할 수도 없습니다. 또한 아직 생성되지 않은 콘텐츠도 생성되지 않습니다.

이 함수는 전역 정적 객체의 초기 조건을 확인할 수 있고 비용이 많이 드는 구성 작업을 피하고 싶을 때 유용합니다.

예를 들어 다음 코드 샘플에서 이 함수는 globalState 이라는 전역 정적 객체의 생성을 단락시키고 기본값을 반환하는 데 사용됩니다:

Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
    if (globalState.exists())
        return globalState->someState;
    return QString();
}

스레드안전 알림: 이 함수는 언제든 모든 스레드에서 호출할 수 있고 항상 유효한 응답을 반환한다는 점에서 스레드 안전합니다. 그러나 구조의 비원자적 특성으로 인해 이 함수는 구조가 완료된 후 짧은 시간 동안 거짓을 반환할 수 있습니다.

메모리 순서 알림: 이 함수는 메모리 순서를 보장하지 않습니다. 대신 콘텐츠에 대한 포인터나 참조를 반환하는 접근자 함수에 의해 제공됩니다. 접근자 함수를 우회하여 생성자가 설정한 일부 전역 상태에 접근하려는 경우 QAtomicInt 또는 QAtomicPointer 에서 제공하는 올바른 메모리 순서 지정 시맨틱을 사용해야 합니다.

isDestroyed()도 참조하세요 .

[noexcept] bool QGlobalStatic::isDestroyed() const

이 함수는 전역 정적 객체가 이미 소멸을 완료한 경우(즉, 해당 유형의 소멸자가 이미 반환한 경우) true 을 반환합니다. 특히 소멸이 아직 진행 중인 경우 이 함수는 false 을 반환합니다.

이 함수가 한 번 참을 반환하면 프로그램이 다시 시작되거나 전역 정적이 포함된 플러그인 또는 라이브러리를 언로드했다가 다시 로드할 때까지 다시는 거짓을 반환하지 않습니다.

이 함수는 프로그램 실행 중 언제든 호출해도 안전하며, 실패할 수도 없고 교착 상태를 유발할 수도 없습니다. 또한 콘텐츠가 아직 생성되지 않은 경우에도 콘텐츠를 생성하지 않습니다.

이 함수는 프로그램 종료 시 실행될 수 있는 코드에서 콘텐츠에 계속 액세스할 수 있는지 여부를 확인하는 데 유용합니다.

exists()도 참조하세요 .

QGlobalStatic<Holder>::Type *QGlobalStatic::operator QGlobalStatic<Holder>::Type *()

이 함수는 이 전역 정적 콘텐츠의 주소를 반환합니다. 콘텐츠가 아직 생성되지 않은 경우, 이 함수에 의해 스레드 안전하게 생성됩니다. 콘텐츠가 이미 소멸된 경우, 이 함수는 널 포인터를 반환합니다.

이 함수는 예를 들어 전역 정적의 내용에 대한 포인터를 로컬 변수에 저장하여 함수에 대한 여러 호출을 피하는 데 사용할 수 있습니다. Q_GLOBAL_STATIC ()의 구현은 이미 매우 효율적이지만 성능이 중요한 섹션에서는 컴파일러를 약간 도와주는 것이 유용할 수 있습니다. 예를 들어

Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
    MyType *state = globalState;
    if (!state) {
        // we're in a post-destruction state
        return QString();
    }
    if (state->condition)
        return state->value1;
    else
        return state->value2;
}

operator->() 및 operator*()도 참조하세요 .

QGlobalStatic<Holder>::Type &QGlobalStatic::operator*()

이 함수는 이 전역 정적의 내용에 대한 참조를 반환합니다. 콘텐츠가 아직 생성되지 않은 경우, 이 함수에 의해 스레드 안전하게 생성됩니다.

이 함수는 콘텐츠가 이미 소멸되었는지는 확인하지 않습니다. 객체가 소멸된 후에 이 함수를 호출하면 사용해서는 안 되는 잘못된 참조를 반환합니다.

QGlobalStatic<Holder>::Type *QGlobalStatic::operator->()

이 함수는 이 전역 정적 콘텐츠의 주소를 반환합니다. 콘텐츠가 아직 생성되지 않은 경우, 이 함수에 의해 스레드 안전하게 생성됩니다.

이 함수는 콘텐츠가 이미 소멸되었는지 확인하지 않으며 절대 null을 반환하지 않습니다. 객체가 소멸된 후에 이 함수가 호출되면, 이 함수는 역참조되어서는 안 되는 댕글 포인터를 반환합니다.

매크로 문서

Q_GLOBAL_STATIC(Type, VariableName, ...)

이름이 VariableName 이고 Type 에 대한 포인터로 동작하는 QGlobalStatic 유형의 전역 및 정적 객체를 생성합니다. Q_GLOBAL_STATIC에 의해 생성된 객체는 처음 사용할 때 자체 초기화되므로 애플리케이션이나 라이브러리의 로드 시간이 증가하지 않습니다. 또한 이 객체는 모든 플랫폼에서 스레드 안전 방식으로 초기화됩니다.

Qt 6.3부터 이 매크로는 객체를 초기화하는 데 사용되는 가변 인수를 허용하므로 Q_GLOBAL_STATIC_WITH_ARGS 가 필요하지 않게 되었습니다. 인수는 이전 매크로와 달리 추가 괄호 세트가 필요하지 않다는 점에 유의하세요.

이 매크로의 일반적인 사용법은 다음과 같이 전역 컨텍스트(즉, 함수 본문 외부)에서 사용됩니다:

Q_GLOBAL_STATIC(MyType, myGlobal)

이 매크로는 POD(Plain Old Data, 즉 C++11 용어로 사소한 유형으로 만들어지지 않은)가 아닌 전역 정적 객체를 대체하기 위한 것이므로 이름 그대로입니다. 예를 들어, 다음 C++ 코드는 전역 정적 객체를 생성합니다:

static MyType myGlobal;

MyType 이 생성자, 소멸자가 있는 클래스 또는 구조체이거나 그렇지 않은 비-POD라고 가정하고 Q_GLOBAL_STATIC과 비교했을 때 위 코드에는 다음과 같은 단점이 있습니다:

  • 로드 시 MyType 의 초기화가 필요합니다(즉, 라이브러리 또는 애플리케이션이 로드될 때 MyType 의 기본 생성자가 호출됩니다);
  • 유형이 한 번도 사용되지 않더라도 초기화됩니다;
  • 서로 다른 번역 단위 간의 초기화 및 소멸 순서가 결정되지 않아 초기화 전 또는 소멸 후에 사용할 수 있습니다;

Q_GLOBAL_STATIC 매크로는 처음 사용할 때 스레드 안전 초기화를 보장하고 사용자가 형이 이미 소멸되었는지 쿼리할 수 있도록 하여 사용 후 소멸 문제를 방지함으로써 위의 모든 문제를 해결합니다( QGlobalStatic::isDestroyed() 참조).

생성자 및 소멸자

Q_GLOBAL_STATIC의 경우 Type 유형은 공개적으로 기본 생성 가능하고 공개적으로 소멸 가능해야 합니다. Q_GLOBAL_STATIC_WITH_ARGS()의 경우, 전달된 인수와 일치하는 공용 생성자가 있어야 합니다.

보호되거나 비공개 기본 생성자 또는 소멸자가 있는 유형(Q_GLOBAL_STATIC_WITH_ARGS()의 경우 인자와 일치하는 보호되거나 비공개 생성자)에는 Q_GLOBAL_STATIC을 사용할 수 없습니다. 해당 유형에 이러한 멤버가 보호된 경우 해당 유형에서 파생하여 생성자 및 소멸자를 공개로 생성하여 문제를 해결할 수 있습니다. 해당 유형이 비공개로 되어 있다면 파생하기 전에 친구 선언이 필요합니다.

예를 들어, 보호된 기본 생성자 및/또는 보호된 소멸자가 있는(또는 비공개이지만 MyType 을 친구로 정의하는) 이전에 정의된 MyOtherType 을 기반으로 MyType 을 생성하는 것으로 충분합니다.

class MyType : public MyOtherType { };
Q_GLOBAL_STATIC(MyType, myGlobal)

소멸자는 암시적 멤버이며 다른 생성자가 정의되지 않은 경우 기본 생성자도 마찬가지이므로 MyType 에 대한 본문은 필요하지 않습니다. 그러나 Q_GLOBAL_STATIC_WITH_ARGS()와 함께 사용하려면 적절한 생성자 본문이 필요합니다:

class MyType : public MyOtherType
{
public:
    MyType(int i) : MyOtherType(i) {}
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))

또는 컴파일러가 C++11 상속 생성자를 지원하는 경우 작성할 수 있습니다:

class MyType : public MyOtherType
{
public:
    using MyOtherType::MyOtherType;
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))

배치

Q_GLOBAL_STATIC 매크로는 전역 범위에서 반드시 정적인 유형을 생성합니다. 함수 내부에 Q_GLOBAL_STATIC 매크로를 배치할 수 없습니다(그렇게 하면 컴파일 오류가 발생합니다).

더 중요한 것은 이 매크로는 헤더가 아닌 소스 파일에 배치해야 한다는 것입니다. 결과 객체에는 정적 링크가 있으므로 매크로를 헤더에 배치하고 여러 소스 파일에 포함시키면 객체가 여러 번 정의되어 링크 오류가 발생하지 않습니다. 대신 각 번역 단위가 서로 다른 개체를 참조하므로 미묘하고 추적하기 어려운 오류가 발생할 수 있습니다.

이 매크로는 POD이거나 C++11 constexpr 생성자(사소하게 생성 및 소멸 가능)가 있는 유형에는 사용하지 않는 것이 좋습니다. 이러한 유형의 경우 전역 또는 함수-로컬 등 일반 정적을 사용하는 것이 좋습니다.

이 매크로는 작동하지만 불필요한 오버헤드가 추가됩니다.

재진입, 스레드 안전, 교착 상태 및 예외 안전에 대한 구성

여러 스레드가 동시에 객체를 초기화하려고 시도하는 경우, 하나의 스레드만 초기화를 진행하고 다른 모든 스레드는 완료될 때까지 대기하는 스레드 안전 방식으로 처음 사용할 때 스스로 초기화되는 객체를 생성합니다.

초기화 프로세스에서 예외가 발생하면 초기화가 완료되지 않은 것으로 간주되어 제어권이 객체 사용에 도달하면 다시 시도됩니다. 초기화를 대기 중인 스레드가 있으면 그 중 하나가 깨어나 초기화를 시도합니다.

매크로는 동일한 스레드에서 재진입에 대해 보장하지 않습니다. 생성자 내부에서 전역 정적 객체에 직접 또는 간접적으로 접근하면 반드시 교착 상태가 발생합니다.

또한 두 개의 다른 스레드에서 두 개의 Q_GLOBAL_STATIC 객체가 초기화되고 있고 각 객체의 초기화 시퀀스가 다른 객체에 액세스하는 경우 교착 상태가 발생할 수 있습니다. 따라서 전역 정적 생성자를 단순하게 유지하거나, 그렇지 않은 경우 생성 중에 전역 정적 사용의 상호 종속성이 없는지 확인하는 것이 좋습니다.

소멸

프로그램 수명 동안 QGlobalStatic::exists() 및 QGlobalStatic::isDestroyed() 함수를 제외하고 객체가 사용되지 않는 경우 Type 유형의 콘텐츠는 생성되지 않으며 종료 시간 작업도 발생하지 않습니다.

객체가 생성되면 C atexit 함수와 유사하게 종료 시점에 소멸됩니다. 실제로 대부분의 시스템에서는 종료 전에 라이브러리 또는 플러그인이 메모리에서 언로드되는 경우에도 소멸자가 호출됩니다.

소멸은 프로그램 종료 시 발생하기 때문에 스레드 안전성이 제공되지 않습니다. 여기에는 플러그인 또는 라이브러리 언로드의 경우도 포함됩니다. 또한 소멸자는 예외를 던지지 않아야 하므로 예외 안전도 제공되지 않습니다.

그러나 재진입은 허용됩니다. 소멸하는 동안 전역 정적 객체에 액세스할 수 있으며 반환되는 포인터는 소멸이 시작되기 전과 동일합니다. 소멸이 완료된 후에는 QGlobalStatic API에 명시된 경우를 제외하고는 전역 정적 객체에 대한 액세스가 허용되지 않습니다.

Q_GLOBAL_STATIC_WITH_ARGS(), Q_APPLICATION_STATIC() 및 QGlobalStatic참조하세요 .

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.