"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 템플릿 클래스의 정적 멤버 초기화가 다르게 동작하는 이유는 무엇입니까?

템플릿 클래스의 정적 멤버 초기화가 다르게 동작하는 이유는 무엇입니까?

2024년 11월 14일에 게시됨
검색:521

 Why Does Static Member Initialization in Templated Classes Behave Differently?

템플릿 클래스의 정적 멤버 초기화 복잡성

C의 정적 멤버 초기화는 널리 사용되는 기술이지만 처리할 때 복잡해질 수 있습니다. 템플릿 클래스. 템플릿이 아닌 클래스에서는 중첩된 도우미 구조체를 초기화에 사용할 수 있지만 둘러싸는 클래스가 템플릿일 때 이 접근 방식은 부족합니다.

다음의 간단한 예를 고려하세요.

struct A
{
    static std::string mA;
    static InitHelper mInit;

    static const std::string& getA() { return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;


template
struct B
{
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper() { return mInit; }
};
template
std::string B::mB;
template
typename B::InitHelper B::mInit;

int main()
{
    std::cout ::getB() ::getHelper(); // [2]
}

예상되는 동작:

[1]이 주석 처리되지 않고 [2]가 주석 처리되면 B::mB가 "로 초기화될 것으로 예상됩니다. 안녕하세요 B입니다." 그러나 이는 발생하지 않습니다.

실제 동작:

  • [1] 및 [2]의 댓글: 부작용 없음 발생합니다.
  • [1] 주석 처리되지 않음: B::getB()는 빈 값을 반환합니다. string.
  • [1]과 [2]가 주석 처리되지 않은 경우: B::mB가 올바르게 초기화되었습니다.
  • [1]이 주석 처리되었으며 [2] 주석 처리되지 않음: 정적 초기화 중에 분할 오류가 발생합니다.

이유 불일치:

ISO/IEC C 2003 표준에 따르면 템플릿 멤버는 정의가 필요한 컨텍스트에서 참조될 때 암시적으로 인스턴스화됩니다. 그러나 정적 데이터 멤버 초기화(및 관련 부작용)는 정적 데이터 멤버가 명시적으로 사용되는 경우에만 발생합니다. 이는 템플릿 멤버가 인스턴스화되지 않은 템플릿이나 전체 인스턴스화가 필요하지 않은 다른 컨텍스트에서만 참조되는 경우 해당 정적 데이터 멤버가 초기화되지 않음을 의미합니다.

예제에서 B:: getB()에는 B::mB가 존재해야 하지만 이는 정의(초기화 프로그램 포함)가 아닌 멤버 템플릿 선언의 인스턴스화만 강제합니다. 대조적으로, B::getHelper()는 B::mInit에 대한 참조를 반환하기 때문에 B::mInit 정의가 필요합니다.

해결책:

표준에서는 명시적으로 특수화된 클래스 템플릿 정적 데이터 멤버의 정의가 초기화 순서를 갖는 반면 다른 클래스 템플릿 정적 데이터 멤버의 정의는 순서 없는 초기화를 갖는 것을 금지합니다. 일관된 초기화 순서를 보장하려면 명시적인 특수화를 사용해야 합니다.

최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3