QGlobalStatic Struct
template <typename Holder> struct QGlobalStaticQGlobalStatic 클래스는 전역 정적 객체를 구현하는 데 사용됩니다. 더 보기...
| 헤더: | #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 |
| operator QGlobalStatic<Holder>::Type *() | |
| QGlobalStatic<Holder>::Type & | operator*() |
| QGlobalStatic<Holder>::Type * | operator->() |
매크로
| Q_GLOBAL_STATIC(Type, variableName, ...) |
상세 설명
QGlobalStatic<Holder>는 템플릿 클래스이며, 여기서 Holder 는 Q_GLOBAL_STATIC() 매크로에 의해 생성된 내부 유형입니다. 전역 정적 객체의 사용자 가시 유형은 Type typedef를 통해 액세스할 수 있습니다.
QGlobalStatic 클래스는 Q_GLOBAL_STATIC()이 사용될 때 노출되는 프론트엔드 API입니다. 이 매크로의 요구 사항 및 사용 시기에 대한 설명은 매크로 문서를 참조하십시오.
일반적으로 이 클래스를 직접 사용하는 일은 없으며, 대신 다음과 같이 Q_GLOBAL_STATIC() 매크로를 사용하게 됩니다.
Q_GLOBAL_STATIC(MyType, myGlobal)위의 예제는 myGlobal 이라는 이름의 QGlobalStatic 유형 객체를 생성합니다. 위의 선언 후, myGlobal 객체는 MyType 유형 객체에 대한 포인터인 것처럼 사용할 수 있으며, 정확히 한 번만 초기화된다는 것이 보장됩니다. 포인터로 사용하는 것 외에도, 이 객체는 전역 변수의 현재 상태를 확인하는 두 가지 메서드인 exists()와 isDestroyed()를 제공합니다.
Q_GLOBAL_STATIC()도 참조하십시오 .
멤버 유형 설명서
[alias] QGlobalStatic::Type
이 유형은 Q_GLOBAL_STATIC() 또는 Q_GLOBAL_STATIC_WITH_ARGS() 매크로에 전달되는 Type 매개변수와 동일합니다. 일부 함수의 반환 유형으로 사용됩니다.
멤버 함수 설명서
[noexcept] bool QGlobalStatic::exists() const
이 함수는 전역 정적 객체의 초기화가 이미 완료되었고(즉, 해당 타입의 생성자가 이미 반환된 상태이며) 소멸이 아직 완료되지 않은 경우 ` true `를 반환합니다. 특히, 초기화가 아직 진행 중인 경우 이 함수는 ` false `를 반환한다는 점에 유의하십시오.
이 함수가 한 번이라도 true를 반환한 후에는, 전역 정적 객체가 소멸될 때까지 다시는 false를 반환하지 않습니다. 전역 정적 객체의 소멸은 프로그램 종료 시 또는 해당 전역 정적 객체를 포함하는 플러그인이나 라이브러리가 언로드될 때 발생합니다.
이 함수는 프로그램 실행 중 어느 시점에서나 안전하게 호출할 수 있습니다. 실패할 수 없으며 교착 상태를 유발하지도 않습니다. 또한, 내용이 아직 생성되지 않은 경우 이를 생성하지도 않습니다.
이 함수는 전역 정적 객체의 초기 조건을 파악할 수 있고, 비용이 많이 들 수 있는 생성 작업을 피하고 싶은 경우에 유용합니다.
예를 들어, 다음 코드 예제에서는 이 함수를 사용하여 ` globalState `라는 전역 정적 객체의 생성을 단축하고 기본값을 반환합니다:
Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
if (globalState.exists())
return globalState->someState;
return QString();
}스레드 안전성 주의 사항: 이 함수는 언제든지 어떤 스레드에서든 호출될 수 있으며 항상 유효한 결과를 반환한다는 점에서 스레드 안전합니다. 하지만 생성 작업의 비원자적 특성으로 인해, 생성 작업이 완료된 직후 짧은 시간 동안 이 함수가 false를 반환할 수 있습니다.
메모리 순서 관련 주의사항: 이 함수는 메모리 순서에 대한 어떠한 보장도 제공하지 않습니다. 메모리 순서 보장은 대신 내용에 대한 포인터나 참조를 반환하는 액세서 함수들에 의해 제공됩니다. 액세서 함수를 우회하고 생성자가 설정한 전역 상태에 직접 접근하려는 경우, QAtomicInt 또는 QAtomicPointer 에서 제공하는 올바른 메모리 순서 의미론을 반드시 사용해야 합니다.
isDestroyed()도 참조하십시오 .
[noexcept] bool QGlobalStatic::isDestroyed() const
이 함수는 전역 정적 객체의 소멸이 이미 완료된 경우(즉, 해당 타입의 소멸자가 이미 반환된 경우) ` true `를 반환합니다. 특히, 소멸이 아직 진행 중인 경우 이 함수는 ` false `를 반환한다는 점에 유의하십시오.
이 함수가 한 번이라도 true를 반환한 후에는, 프로그램이 재시작되거나 전역 정적 객체를 포함하는 플러그인 또는 라이브러리가 언로드 및 재로드될 때까지 다시는 false를 반환하지 않습니다.
이 함수는 프로그램 실행 중 어느 시점에서나 안전하게 호출할 수 있습니다. 실패할 수 없으며 교착 상태를 유발하지도 않습니다. 또한, 내용이 아직 생성되지 않은 경우 이를 생성하지도 않습니다.
이 함수는 프로그램 종료 시 실행될 수 있는 코드에서, 해당 콘텐츠에 여전히 접근할 수 있는지 여부를 판단하는 데 유용합니다.
exists()도 참조하십시오 .
QGlobalStatic::operator QGlobalStatic<Holder>::Type *()
이 함수는 이 전역 정적 변수의 내용에 대한 주소를 반환합니다. 내용이 아직 생성되지 않은 경우, 이 함수가 스레드 안전하게 내용을 생성합니다. 내용이 이미 소멸된 경우, 이 함수는 null 포인터를 반환합니다.
예를 들어, 이 함수를 사용하면 전역 정적 변수의 내용에 대한 포인터를 지역 변수에 저장할 수 있으므로, 함수를 여러 번 호출하는 것을 피할 수 있습니다. Q_GLOBAL_STATIC()의 구현은 이미 상당히 효율적이지만, 성능이 중요한 부분에서는 컴파일러를 약간 도와주는 것이 유용할 수 있습니다. 예를 들면 다음과 같습니다.
Q_GLOBAL_STATIC(MyType, globalState)
QString someState()
{
if (globalState::isDestroyed())
return QString();
MyType *state = globalState;
if (state->condition)
return state->value;
else
return state->worth;
}operator->() 및 operator*()도 참조하십시오 .
QGlobalStatic<Holder>::Type &QGlobalStatic::operator*()
이 함수는 이 전역 정적 변수의 내용에 대한 참조를 반환합니다. 내용이 아직 생성되지 않은 경우, 이 함수에 의해 스레드 안전하게 생성됩니다.
이 함수는 해당 내용이 이미 소멸되었는지 여부를 확인하지 않습니다. 객체가 소멸된 후에 이 함수가 호출되면, 사용해서는 안 되는 무효한 참조를 반환합니다.
exists() 및 isDestroyed()도 참조하십시오 .
QGlobalStatic<Holder>::Type *QGlobalStatic::operator->()
이 함수는 이 전역 정적 변수의 내용에 대한 주소를 반환합니다. 내용이 아직 생성되지 않은 경우, 이 함수에 의해 스레드 안전하게 생성됩니다.
이 함수는 내용이 이미 소멸되었는지 여부를 확인하지 않으며, 절대 null을 반환하지 않습니다. 객체가 소멸된 후에 이 함수가 호출되면, 참조해서는 안 되는 매달린 포인터를 반환합니다.
exists() 및 isDestroyed()도 참조하십시오 .
매크로 문서
Q_GLOBAL_STATIC(Type, variableName, ...)
QGlobalStatic 타입의 전역 정적 객체를 variableName 라는 이름으로 생성합니다. 이 객체는 Type 에 대한 포인터처럼 동작합니다. 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;Q_GLOBAL_STATIC과 비교했을 때, MyType 가 생성자나 소멸자를 갖거나 그 외의 이유로 POD가 아닌 클래스 또는 구조체라고 가정할 경우, 후자는 다음과 같은 단점이 있습니다:
myGlobal의 로드 시 초기화가 필요합니다(즉, 라이브러리나 애플리케이션이 로드될 때MyType의 기본 생성자가 호출됩니다);- 객체가 한 번도 사용되지 않더라도 초기화됩니다;
- 서로 다른 번역 단위 간의 초기화 및 소멸 순서가 정해지지 않아, 다른 전역 변수의 생성자나 소멸자에 의해 초기화 전이나 소멸 후에 해당 객체가 사용될 가능성이 있습니다.
Q_GLOBAL_STATIC 매크로는 첫 사용 시 스레드 안전 초기화를 보장하고, 사용자가 해당 유형이 이미 소멸되었는지 여부를 조회할 수 있게 함으로써 소멸 후 사용(use-after-destruction) 문제를 방지함으로써 이러한 모든 문제를 해결합니다( QGlobalStatic::isDestroyed() 참조).
생성자 및 소멸자
Q_GLOBAL_STATIC의 경우, 유형과 변수 이름만 지정된 경우 해당 Type 는 공개적으로 기본 생성 가능하고 공개적으로 소멸 가능해야 합니다. 그렇지 않은 경우, Type 는 매크로의 나머지 인수를 받는 공용 생성자를 가져야 합니다. Q_GLOBAL_STATIC_WITH_ARGS()의 경우, 매크로의 세 번째 인수를 매개변수 목록으로 받아들이는 공용 생성자가 있어야 합니다.
관련 생성자나 소멸자가 protected 또는 private으로 선언된 Type 과 함께 Q_GLOBAL_STATIC을 사용할 수는 없습니다. 해당 타입이 해당 멤버를 protected로 선언한 경우, 해당 타입을 상속받아 public 생성자와 소멸자를 생성함으로써 이 문제를 해결할 수 있습니다. 타입이 해당 멤버를 private으로 선언한 경우, 상속하기 전에 friend 선언이 필요합니다.
예를 들어, 보호된 기본 생성자 및/또는 보호된 소멸자를 가진(또는 이를 사적으로 선언하되 ` MyType `를 친구로 선언한) 미리 정의된 ` MyOtherType `를 기반으로 ` MyType `를 생성하려면 다음 코드만으로도 충분합니다.
class MyType : public MyOtherType { };
Q_GLOBAL_STATIC(MyType, myGlobal)파괴자는 암시적 멤버이며, 다른 생성자가 정의되지 않은 경우 기본 생성자도 암시적 멤버이므로 MyType 의 본문은 필요하지 않습니다. 그러나 Type 및 variableName 뒤에 인자를 사용하여 호출하거나 Q_GLOBAL_STATIC_WITH_ARGS()와 함께 사용하려면 적절한 생성자 본문이 필요합니다:
class MyType : public MyOtherType
{
public:
MyType(int i) : MyOtherType(i) {}
};
Q_GLOBAL_STATIC(MyType, myGlobal, 42)또는 (C++11에서 상속 생성자가 도입되었으므로) 다음과 같이 작성할 수도 있습니다:
class MyType : public MyOtherType
{
public:
using MyOtherType::MyOtherType;
};
Q_GLOBAL_STATIC_WITH_ARGS(MyType, myGlobal, (42))배치
Q_GLOBAL_STATIC 매크로는 전역 범위에서 타입을 생성하고, 해당 타입의 변수를 반드시 정적(static)으로 선언합니다. Q_GLOBAL_STATIC 매크로를 함수 내부나 클래스 본문 내에 배치할 수는 없습니다(이렇게 하면 컴파일 오류가 발생합니다).
더 중요한 점은, 이 매크로는 헤더 파일이 아닌 소스 파일에 배치해야 한다는 것입니다. 생성된 객체는 정적 링크를 가지므로, 매크로를 헤더 파일에 배치하고 여러 소스 파일에서 이를 포함할 경우, 객체가 여러 번 정의되더라도 링크 오류는 발생하지 않습니다. 대신 각 번역 단위는 서로 다른 객체를 참조하게 되어, 미묘하고 추적하기 어려운 오류를 유발할 수 있습니다.
권장되지 않는 사용법
이 매크로는 POD 유형이나 C++11 constexpr 생성자(사소하게 생성 및 소멸 가능한)를 가진 유형과 함께 사용하는 것은 권장되지 않습니다. 이러한 유형의 경우, 전역이든 함수 국소적이든 상관없이 일반적인 static을 사용하는 것이 여전히 권장됩니다.
이 매크로는 작동하겠지만, 불필요한 오버헤드를 발생시킵니다.
생성 시 재진입성, 스레드 안전성, 교착 상태 및 예외 안전성
Q_GLOBAL_STATIC 매크로는 스레드 안전 방식으로 첫 사용 시 자체 초기화되는 객체를 생성합니다. 즉, 여러 스레드가 동시에 객체를 초기화하려고 시도할 경우, 단 하나의 스레드만 초기화를 진행하며 나머지 모든 스레드는 완료될 때까지 대기합니다.
초기화 과정에서 예외가 발생하면 초기화는 완료되지 않은 것으로 간주되며, 객체가 사용되는 시점에 도달하면 다시 시도됩니다. 초기화를 기다리는 스레드가 있는 경우, 그중 하나가 깨어나 초기화를 시도하게 됩니다.
이 매크로는 동일한 스레드에서의 재진입에 대해서는 어떠한 보장도 하지 않습니다. 전역 정적 객체가 자체 생성자 내부에서 직접 또는 간접적으로 액세스될 경우, 반드시 교착 상태가 발생합니다.
또한, 두 개의 서로 다른 스레드에서 두 개의 Q_GLOBAL_STATIC 객체가 초기화되고, 각 객체의 초기화 순서에서 다른 객체에 접근하는 경우, 교착 상태가 발생할 수 있습니다. 따라서 전역 정적 생성자는 단순하게 유지하거나, 그렇지 못할 경우 생성 과정에서 전역 정적 객체의 사용 간에 상호 의존성이 없도록 하는 것이 좋습니다.
소멸
프로그램의 수명 기간 동안 객체가 사용되지 않는 경우, QGlobalStatic::exists() 및 QGlobalStatic::isDestroyed() 함수를 제외하면 Type 유형의 내용은 생성되지 않으며 종료 시점 작업도 수행되지 않습니다.
객체가 생성된 경우, C 언어의 atexit() 함수와 마찬가지로 프로그램 종료 시점에 소멸됩니다. 실제로 대부분의 시스템에서, 종료 전에 라이브러리나 플러그인이 메모리에서 언로드되더라도 소멸자가 호출됩니다.
소멸은 프로그램 종료 시에 이루어지도록 의도되었으므로, 스레드 안전성이 보장되지 않습니다. 여기에는 플러그인이나 라이브러리가 언로드되는 경우도 포함됩니다. 또한, 소멸자가 예외를 던져서는 안 되므로 예외 안전성도 보장되지 않습니다.
그러나 재진입성은 허용됩니다. 소멸 과정 중에는 전역 정적 객체에 접근할 수 있으며, 반환되는 포인터는 소멸이 시작되기 전과 동일합니다. 소멸이 완료된 후에는 QGlobalStatic API에 명시된 경우를 제외하고 전역 정적 객체에 접근할 수 없습니다.
Q_APPLICATION_STATIC() 및 QGlobalStatic도 참조하십시오 .
© 2026 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.