Namespaces
Variants

static members

From 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 키워드를 포함합니다. static 키워드는 일반적으로 다른 지정자 앞에 나타나며 (이 때문에 구문이 비공식적으로 static data-member 또는 static member-function 으로 설명됩니다), 하지만 지정자 시퀀스의 어느 위치에도 나타날 수 있습니다.

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

설명

클래스의 정적 멤버들은 클래스 객체와 연관되지 않습니다: 이들은 정적 또는 스레드 (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 로 선언될 수 없습니다.

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

정적 데이터 멤버

정적 데이터 멤버는 어떤 객체와도 연관되지 않습니다. 클래스의 객체가 정의되지 않더라도 존재합니다. 정적 데이터 멤버의 인스턴스는 전체 프로그램에서 오직 하나만 존재하며 정적 storage duration 을 가지며, thread_local 키워드가 사용된 경우에는 스레드당 하나의 객체가 thread storage duration을 가집니다 (since 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]

참고 항목