Namespaces
Variants

static members

From ko.cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous

클래스 정의 내부에서, 키워드 static 는 클래스 인스턴스에 바인딩되지 않는 멤버들을 선언합니다.

클래스 정의 외부에서는 다른 의미를 가집니다: storage duration 을 참조하십시오.

목차

구문

정적 멤버에 대한 선언은 선언 지정자에 키워드 static이 포함된 멤버 선언입니다. 키워드 staticstaticstatic은 일반적으로 다른 지정자 앞에 나타나지만(따라서 구문을 비공식적으로 static static member-declaration이라고 설명하기도 함), 지정자 시퀀스의 어느 위치에나 올 수 있습니다.

모든 정적 데이터 멤버와 정적 멤버 함수의 이름은 포함하는 클래스의 이름과 달라야 합니다.

설명

클래스의 정적 멤버들은 클래스 객체와 연관되지 않습니다: 이들은 정적 또는 스레드 (since C++11) storage duration 을 가지는 독립 변수이거나 일반 함수입니다.

static 키워드는 클래스 정의 내부에서 static 멤버의 선언에만 사용되며, 해당 static 멤버의 정의에는 사용되지 않습니다:

class X { static int n; }; // 선언 ('static' 사용)
int X::n = 1;              // 정의 ('static' 사용하지 않음)

클래스 본문 내의 선언은 정의가 아니며, 멤버를 불완전한 타입 ( void 제외)으로 선언할 수 있으며, 여기에는 해당 멤버가 선언된 타입 자체도 포함됩니다:

struct Foo;
struct S
{
    static int a[]; // 선언, 불완전 타입
    static Foo x;   // 선언, 불완전 타입
    static S s;     // 선언, 불완전 타입 (자체 정의 내부)
};
int S::a[10]; // 정의, 완전 타입
struct Foo {};
Foo S::x;     // 정의, 완전 타입
S S::s;       // 정의, 완전 타입

그러나 선언이 constexpr 또는 inline (C++17부터) 지정자를 사용하는 경우, 해당 멤버는 완전한 타입으로 선언되어야 합니다.

(C++11부터)

클래스 T 의 정적 멤버 m 를 참조하기 위해 두 가지 형식을 사용할 수 있습니다: 한정된 이름 T::m 또는 멤버 접근 표현식 E.m 또는 E->m , 여기서 E 는 각각 T 또는 T* 로 평가되는 표현식입니다. 동일한 클래스 범위 내에서는 한정이 불필요합니다:

struct X
{
    static void f(); // 선언
    static int n;    // 선언
};
X g() { return X(); } // X를 반환하는 함수
void f()
{
    X::f();  // X::f는 정적 멤버 함수의 한정된 이름
    g().f(); // g().f는 정적 멤버 함수를 참조하는 멤버 접근 표현식
}
int X::n = 7; // 정의
void X::f() // 정의
{
    n = 1; // X::n은 이 스코프에서 단순히 n으로 접근 가능
}

정적 멤버는 클래스 멤버 접근 규칙(private, protected, public) 을 따릅니다.

정적 멤버 함수

정적 멤버 함수는 어떤 객체와도 연관되지 않습니다. 호출될 때, 이들은 this 포인터를 가지지 않습니다.

정적 멤버 함수는 virtual , const , volatile , 또는 ref-qualified 로 선언될 수 없습니다.

정적 멤버 함수의 주소는 일반적인 함수 포인터 에 저장될 수 있지만, 멤버 함수 포인터 에는 저장될 수 없습니다.

정적 데이터 멤버

는 어떤 객체와도 연결되지 않습니다. 클래스의 객체가 정의되지 않아도 존재합니다. 정적 데이터 멤버는 정적 저장 기간을 가지며 프로그램 전체에 하나의 인스턴스만 존재합니다. 단, thread_local 키워드를 사용하는 경우 스레드 저장 기간을 가지며 스레드당 하나의 객체가 존재합니다(C++11부터).

정적 데이터 멤버는 mutable일 수 없습니다.

네임스페이스 범위에 있는 클래스의 정적 데이터 멤버는 외부 링크를 가집니다. 단, 클래스 자체가 외부 링크를 가지는 경우(즉, 명명되지 않은 네임스페이스의 멤버가 아닌 경우)에만 해당됩니다. 지역 클래스(함수 내부에 정의된 클래스)와 명명되지 않은 클래스(명명되지 않은 클래스의 멤버 클래스 포함)는 정적 데이터 멤버를 가질 수 없습니다.

정적 데이터 멤버는 inline으로 선언될 수 있습니다. 인라인 정적 데이터 멤버는 클래스 정의 내에서 정의될 수 있으며 초기화자를 지정할 수 있습니다. 클래스 외부에서의 정의가 필요하지 않습니다:

struct X
{
    inline static int fully_usable = 1; // No out-of-class definition required,
                                        // ODR-usable
    inline static const std::string class_name{"X"}; // Likewise

    static const int non_addressable = 1; // C.f. non-inline constants, usable
                                          // for its value, but not ODR-usable
    // static const std::string class_name{"X"}; // Non-integral declaration of this
                                                 // form is disallowed entirely
};
(C++17부터)

상수 정적 멤버

정수형이나 열거형의 정적 데이터 멤버가 const (그리고 volatile 가 아닌)로 선언된 경우, 모든 표현식이 초기화 에서 상수 표현식 인 이니셜라이저를 사용하여 클래스 정의 내부에서 직접 초기화될 수 있습니다:

struct X
{
    const static int n = 1;
    const static int m{2}; // C++11부터
    const static int k;
};
const int X::k = 3;

LiteralType 의 정적 데이터 멤버가 constexpr 로 선언된 경우, 모든 표현식이 상수 표현식인 초기화자를 사용하여 클래스 정의 내부에서 바로 초기화되어야 합니다:

struct X
{
    constexpr static int arr[] = { 1, 2, 3 };        // OK
    constexpr static std::complex<double> n = {1,2}; // OK
    constexpr static int k; // Error: constexpr static requires an initializer
};
(C++11부터)

const non-inline (since C++17) static 데이터 멤버 또는 constexpr static 데이터 멤버 (since C++11) (until C++17) 가 ODR-use 되는 경우, 네임스페이스 범위에서의 정의가 여전히 필요하지만 초기화자를 가질 수 없습니다.

constexpr 정적 데이터 멤버는 암시적으로 inline 이며 네임스페이스 범위에서 재선언할 필요가 없습니다. 초기화자 없이 재선언하는 것(이전에는 필요했음)은 여전히 허용되지만, 사용이 권장되지 않습니다.

(C++17부터)
struct X
{
    static const int n = 1;
    static constexpr int m = 4;
};
const int *p = &X::n, *q = &X::m; // X::n과 X::m은 ODR-사용됨
const int X::n;             // … 따라서 정의가 필요함
constexpr int X::m;         // … (C++17에서는 X::m 제외)

키워드

static

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 194 C++98 (static) 멤버 함수 이름이 클래스 이름과 같을 수 있음 명명 제한이 추가됨 (including
non-static member functions )

참고문헌

  • C++23 표준 (ISO/IEC 14882:2024):
  • 11.4.9 정적 멤버 [class.static]
  • C++20 표준(ISO/IEC 14882:2020):
  • 11.4.8 정적 멤버 [class.static]
  • C++17 표준(ISO/IEC 14882:2017):
  • 12.2.3 정적 멤버 [class.static]
  • C++14 표준(ISO/IEC 14882:2014):
  • 9.4 정적 멤버 [class.static]
  • C++11 표준 (ISO/IEC 14882:2011):
  • 9.4 정적 멤버 [class.static]
  • C++98 표준(ISO/IEC 14882:1998):
  • 9.4 정적 멤버 [class.static]

참고 항목