다음을 통해 공유


C++ 형식 시스템

형식개념은 C++에서 중요합니다. 모든 변수, 함수 인수 및 함수 반환 값은 형식이 있어야 컴파일할 수 있습니다. 또한 모든 식(리터럴 값 포함)은 평가되기 전에 컴파일러에서 암시적으로 형식을 부여합니다. 형식의 몇 가지 예로는 정수 값을 저장하거나 부 double 동 소수점 값을 저장하는 것과 같은 int 기본 제공 형식 또는 텍스트를 저장할 클래스 std::basic_string 와 같은 표준 라이브러리 형식이 있습니다. 또는 struct을 정의하여 고유한 형식을 class 만들 수 있습니다. 형식은 변수(또는 식 결과)에 할당된 메모리 양을 지정합니다. 또한 이 형식은 저장할 수 있는 값의 종류, 컴파일러가 해당 값의 비트 패턴을 해석하는 방법 및 해당 값에 대해 수행할 수 있는 작업을 지정합니다. 이 문서에는 C++ 형식 시스템의 주요 기능에 대한 비공식적 개요가 들어 있습니다.

용어

스칼라 형식: 정의된 범위의 단일 값을 보유하는 형식입니다. 스칼라에는 산술 형식(정수 또는 부동 소수점 값), 열거형 형식 멤버, 포인터 형식, 포인터-멤버 형식 및 std::nullptr_t. 기본 형식은 일반적으로 스칼라 형식입니다.

복합 형식: 스칼라 형식이 아닌 형식입니다. 복합 형식에는 배열 형식, 함수 형식, 클래스(또는 구조체) 형식, 공용 구조체 형식, 열거형, 참조 및 비정적 클래스 멤버에 대한 포인터가 포함됩니다.

변수: 데이터 수량의 기호화된 이름입니다. 이 이름은 정의된 코드 범위 전체에서 참조하는 데이터에 액세스하는 데 사용할 수 있습니다. C++에서 변수는 스칼라 데이터 형식의 인스턴스를 참조하는 데 자주 사용되는 반면, 다른 형식의 인스턴스는 일반적으로 개체라고 합니다.

개체: 단순성과 일관성을 위해 이 문서에서는 개체라는 용어를 사용하여 클래스 또는 구조체의 인스턴스를 참조합니다. 일반적으로 사용되는 경우 모든 형식, 심지어 스칼라 변수도 포함됩니다.

POD 형식 (일반 이전 데이터): C++의 이 비공식적인 데이터 형식 범주는 스칼라(기본 형식 섹션 참조) 또는 POD 클래스인 형식을 나타냅니다. POD 클래스에는 POD가 아닌 정적 데이터 멤버가 없으며 사용자 정의 생성자, 사용자 정의 소멸자 또는 사용자 정의 할당 연산자가 없습니다. 또한 POD 클래스에는 가상의 함수, 기본 클래스 및 비공개 또는 보호된 비정적 데이터 멤버가 없습니다. POD 유형은 주로 외부 데이터 교환(예: POD 유형만 있는 C 언어로 작성된 모듈)에 사용됩니다.

변수 및 함수 형식 지정

C++는 강력한 형식의 언어와 정적으로 형식화된 언어입니다. 모든 개체에는 형식이 있으며 해당 형식은 변경되지 않습니다. 코드에서 변수를 선언할 때 해당 형식을 명시적으로 지정하거나 키워드(keyword) 사용하여 auto 컴파일러에 이니셜라이저에서 형식을 추론하도록 지시해야 합니다. 코드에서 함수를 선언할 때는 해당 반환 값의 형식과 각 인수의 형식을 지정해야 합니다. 함수에서 반환되는 값이 없는 경우 반환 값 형식 void 을 사용합니다. 예외는 임의의 형식의 인수를 허용하는 함수 템플릿을 사용하는 경우입니다.

변수를 처음 선언한 후에는 나중에 해당 형식을 변경할 수 없습니다. 그러나 변수의 값 또는 함수의 반환 값을 다른 형식의 다른 변수로 복사할 수 있습니다. 이러한 작업을 형식 변환이라고 하며, 때로는 필요하지만 데이터 손실 또는 올바르지 않은 잠재적 원인이기도 합니다.

POD 형식의 변수를 선언할 때 초기화하는 것이 좋습니다. 즉, 초기 값을 지정합니다. 변수를 초기화할 때까지 해당 메모리 위치에 이전에 있던 비트로 구성된 "가비지" 값을 가지고 있습니다. 특히 초기화를 처리하는 다른 언어에서 온 경우 기억해야 할 C++의 중요한 측면입니다. POD가 아닌 클래스 형식의 변수를 선언하면 생성자가 초기화를 처리합니다.

다음 예제에서는 각각에 대한 일부 설명을 포함한 몇 가지 간단한 변수 선언을 보여 줍니다. 또한 컴파일러가 특정 변수의 후속 작업을 허용하거나 거부하기 위해 형식 정보를 사용하는 방법을 보여줍니다.

int result = 0;              // Declare and initialize an integer.
double coefficient = 10.8;   // Declare and initialize a floating
                             // point value.
auto name = "Lady G.";       // Declare a variable and let compiler
                             // deduce the type.
auto address;                // error. Compiler cannot deduce a type
                             // without an intializing value.
age = 12;                    // error. Variable declaration must
                             // specify a type or use auto!
result = "Kenny G.";         // error. Can't assign text to an int.
string result = "zero";      // error. Can't redefine a variable with
                             // new type.
int maxValue;                // Not recommended! maxValue contains
                             // garbage bits until it is initialized.

기본(기본 제공) 형식

일부 언어와 달리, C++에는 다른 형식이 파생되는 유니버설 기본 형식이 없습니다. 언어에는 기본 제공 형식이라고도 하는 많은 기본 형식이 포함됩니다. 이러한 형식에는 각각 ASCII 및 wchar_t UNICODE 문자에 char 대한 숫자 형식(예: int, doublelong, bool및 형식)이 포함됩니다. 대부분의 정수 계열 기본 형식(, double, wchar_t및 관련 형식 제외bool)에는 unsigned 모두 변수가 저장할 수 있는 값 범위를 수정하는 버전이 있습니다. 예를 들어 int부가된 32비트 정수는 -2,147,483,648에서 2,147,483,647까지의 값을 나타낼 수 있습니다. 32비트로도 저장되는 이 unsigned int값은 0에서 4,294,967,295까지 저장할 수 있습니다. 각 사례에서 사용할 수 있는 값의 총 수는 동일하며, 범위만 다릅니다.

컴파일러는 이러한 기본 제공 형식을 인식하며, 이러한 형식에 대해 수행할 수 있는 작업과 다른 기본 형식으로 변환할 수 있는 방법을 제어하는 기본 제공 규칙이 있습니다. 기본 제공 형식 및 해당 크기 및 숫자 제한의 전체 목록은 기본 제공 형식을 참조하세요.

다음 그림에서는 Microsoft C++ 구현에서 기본 제공 형식의 상대적 크기를 보여 줍니다.

Diagram of the relative size in bytes of several built in types.

다음 표에서는 Microsoft C++ 구현에서 가장 자주 사용되는 기본 형식 및 해당 크기를 나열합니다.

Type 크기 설명
int 4바이트 정수 값에 대한 기본 선택입니다.
double 8바이트 부동 소수점 값에 대한 기본 선택입니다.
bool 1바이트 true 또는 false가 될 수 있는 값을 나타냅니다.
char 1바이트 UNICODE로 변환되지 않는 이전 C 스타일 문자열 또는 std::string 개체의 ASCII 문자에 사용합니다.
wchar_t 2바이트 UNICODE 형식(Windows의 경우 UTF-16, 운영 체제마다 다를 수 있음)으로 인코딩할 수 있는 "와이드" 문자 값을 나타냅니다. wchar_t 는 형식의 문자열에 사용되는 문자 형식 std::wstring입니다.
unsigned char 1바이트 C++에는 기본 제공 바이트 형식이 없습니다. 바이트 값을 나타내는 데 사용합니다 unsigned char .
unsigned int 4바이트 비트 플래그에 대한 기본 선택입니다.
long long 8바이트 훨씬 더 큰 정수 값 범위를 나타냅니다.

다른 C++ 구현은 특정 숫자 형식에 서로 다른 크기를 사용할 수 있습니다. C++ 표준에 필요한 크기 및 크기 관계에 대한 자세한 내용은 기본 제공 형식을 참조 하세요.

void 형식

형식은 void 특수 형식입니다. 형식 void의 변수를 선언할 수는 없지만 형식 변수 void * (포인터)를 선언할 void수 있습니다. 이 변수는 원시(형식화되지 않은) 메모리를 할당할 때 필요한 경우가 있습니다. 그러나 포인터는 void 형식이 안전하지 않으며 최신 C++에서는 사용하지 않는 것이 좋습니다. 함수 선언 void 에서 반환 값은 함수가 값을 반환하지 않음을 의미합니다. 반환 형식으로 사용하는 것이 일반적이며 허용 가능한 용도 void입니다. 예를 들어 fn(void)C 언어에서는 매개 변수 목록에서 선언 void 할 매개 변수가 없는 함수가 필요하지만 최신 C++에서는 이 방법을 사용하지 않는 것이 좋습니다. 매개 변수가 없는 함수는 선언fn()해야 합니다. 자세한 내용은 형식 변환 및 형식 안전을 참조하세요.

const 형식 한정자

모든 기본 제공 또는 사용자 정의 형식은 키워드(keyword) 의해 const 정규화될 수 있습니다. 또한 멤버 함수는 정규화되고 심지어 오버로드될 const수도 const있습니다. 형식의 const 값은 초기화된 후에 수정할 수 없습니다.

const double PI = 3.1415;
PI = .75; //Error. Cannot modify const variable.

한정자는 const 함수 및 변수 선언에서 광범위하게 사용되며 "const 정확성"은 C++의 중요한 개념입니다. 기본적으로 컴파일 시 값이 의도치 않게 수정되지 않도록 보장하는 데 사용됩니다 const . 자세한 내용은 const를 참조하세요.

const 형식은 버전이 아닌 형식과 다릅니다const. 예를 들어 const intint. 변수에서 const-ness를 제거해야 하는 드문 경우에서 C++ const_cast 연산자를 사용할 수 있습니다. 자세한 내용은 형식 변환 및 형식 안전을 참조하세요.

String 형식

엄밀히 말하면 C++ 언어에는 기본 제공 문자열 형식이 없습니다. charwchar_t 단일 문자 저장 - 마지막 유효한 문자(C 스타일 문자열이라고도 함)를 지나서 배열 요소에 종결 null 값(예: ASCII'\0')을 추가하여 문자열 근사치로 이러한 형식의 배열을 선언해야 합니다. 훨씬 더 많은 코드를 작성해야 하거나 외부 문자열 유틸리티 라이브러리 함수를 사용해야 하는 C 스타일 문자열입니다. 그러나 최신 C++에서는 표준 라이브러리 형식 std::string (8비트 char-type 문자열의 경우) 또는 std::wstring (16비트 wchar_t-type 문자열의 경우) 이러한 C++ 표준 라이브러리 컨테이너는 모든 준수 C++ 빌드 환경에 포함된 표준 라이브러리의 일부이기 때문에 네이티브 문자열 형식으로 간주할 수 있습니다. 지시문을 #include <string> 사용하여 프로그램에서 이러한 형식을 사용할 수 있도록 합니다. (MFC 또는 ATL CString 을 사용하는 경우 클래스도 사용할 수 있지만 C++ 표준에는 속하지 않습니다.) null로 끝나는 문자 배열(이전에 멘션 C 스타일 문자열)을 사용하는 것은 최신 C++에서 권장되지 않습니다.

사용자 정의 형식

또는 structunionenum해당 구문을 정의class할 때 해당 구문은 기본 형식인 것처럼 코드의 나머지 부분에 사용됩니다. 메모리 크기는 잘 알려져 있고, 사용법에 관한 규정이 컴파일 시간 검사, 가동 시 프로그램 수명 점검을 위해 적용됩니다. 기본 제공 형식과 사용자 정의 형식 간 기본적 차이는 다음과 같습니다.

  • 컴파일러는 기본적으로 사용자 정의 형식을 인식하지 못합니다. 컴파일 프로세스 중에 정의가 처음 발견되면 형식에 대해 알아봅니다.

  • 오버로드를 통해 적합한 연산자를 클래스 멤버 또는 비멤버 함수로 정의하여 해당 형식에서 수행할 수 있는 연산자와 다른 형식으로 변환할 수 있는 방법을 지정합니다. 자세한 내용은 함수 오버로드를 참조 하세요.

포인터 형식

C 언어의 초기 버전과 마찬가지로 C++는 특수 선언자 * (별표)를 사용하여 포인터 형식의 변수를 선언할 수 있도록 계속합니다. 포인터 형식은 메모리에서 실제 데이터 값이 저장되는 위치의 주소를 저장합니다. 최신 C++에서는 이러한 포인터 형식을 원시 포인터라고 하며 특수 연산자 * (별표) 또는 -> (보다 크고 자주 화살표라고도 하는 대시)를 통해 코드에서 액세스합니다. 이 메모리 액세스 작업을 역참조라고 합니다. 사용하는 연산자는 스칼라에 대한 포인터 또는 개체의 멤버에 대한 포인터를 역참조하는지에 따라 달라집니다.

포인터 형식 사용은 C 및 C++ 프로그램 개발 환경에서 가장 까다롭고 복잡한 요소 중 하나였습니다. 이 섹션에서는 원하는 경우 원시 포인터를 사용하는 데 도움이 되는 몇 가지 사실과 사례를 간략하게 설명합니다. 그러나 최신 C++에서는 스마트 포인터의 진화 (이 섹션의 끝에 자세히 설명됨)로 인해 개체 소유권에 원시 포인터 를 사용하는 것이 더 이상 필요하지 않습니다(또는 권장). 개체를 관찰하기 위해 원시 포인터를 사용하는 것은 여전히 유용하고 안전합니다. 그러나 개체 소유권에 사용해야 하는 경우 소유하는 개체를 만들고 소멸하는 방법을 신중하게 고려해야 합니다.

가장 먼저 알아야 할 것은 원시 포인터 변수 선언이 주소를 저장할 충분한 메모리만 할당한다는 것입니다. 포인터가 역참조될 때 참조하는 메모리 위치입니다. 포인터 선언은 데이터 값을 저장하는 데 필요한 메모리를 할당하지 않습니다. (해당 메모리를 백업 저장소라고도 합니다.) 즉, 원시 포인터 변수를 선언하여 실제 데이터 변수가 아닌 메모리 주소 변수를 만듭니다. 포인터 변수에 백업 저장소에 대한 유효한 주소가 포함되어 있는지 확인하기 전에 포인터 변수를 역참조하는 경우 프로그램에서 정의되지 않은 동작(일반적으로 심각한 오류)이 발생합니다. 다음 예제에서는 이런 종류의 오류를 보여 줍니다.

int* pNumber;       // Declare a pointer-to-int variable.
*pNumber = 10;      // error. Although this may compile, it is
                    // a serious error. We are dereferencing an
                    // uninitialized pointer variable with no
                    // allocated memory to point to.

이 예제는 실제 정수 데이터 또는 할당된 유효한 메모리 주소를 저장하기 위해 할당된 메모리 없이 포인터를 역참조합니다. 다음은 다음 오류를 해결한 코드입니다.

    int number = 10;          // Declare and initialize a local integer
                              // variable for data backing store.
    int* pNumber = &number;   // Declare and initialize a local integer
                              // pointer variable to a valid memory
                              // address to that backing store.
...
    *pNumber = 41;            // Dereference and store a new value in
                              // the memory pointed to by
                              // pNumber, the integer variable called
                              // "number". Note "number" was changed, not
                              // "pNumber".

수정된 코드 예제는 로컬 스택 메모리를 사용하여 pNumber가 가리키는 백업 저장소를 만듭니다. 간단히 기본 형식을 사용합니다. 실제로 포인터에 대한 백업 저장소는 키워드(keyword) 식을 사용하여 new(또는 자유 저장소)이라는 메모리 영역에 동적으로 할당되는 사용자 정의 형식입니다(C 스타일 프로그래밍에서는 이전 malloc() C 런타임 라이브러리 함수가 사용됨). 할당되면 이러한 변수를 일반적으로 개체라고 하며, 특히 클래스 정의를 기반으로 하는 경우 해당 변수를 개체라고 합니다. 할당된 new 메모리는 해당 delete 문(또는 함수를 사용하여 malloc() 할당한 경우 C 런타임 함수 free())에 의해 삭제되어야 합니다.

그러나 동적으로 할당된 개체를 삭제하는 것은 잊기 쉽습니다. 특히 복잡한 코드에서는 메모리 누수라는 리소스 버그가 발생합니다. 이러한 이유로 원시 포인터의 사용은 최신 C++에서 권장되지 않습니다. 소멸자가 호출될 때 자동으로 메모리를 해제하는 스마트 포인터에 원시 포인터를 래핑하는 것이 거의 항상 좋습니다. 즉, 코드가 스마트 포인터의 범위를 벗어나는 경우입니다. 스마트 포인터를 사용하면 C++ 프로그램에서 전체 버그 클래스를 사실상 제거합니다. 다음 예에서 MyClassDoSomeWork();의 공용 메서드를 가진 사용자 정의 형식입니다.

void someFunction() {
    unique_ptr<MyClass> pMc(new MyClass);
    pMc->DoSomeWork();
}
  // No memory leak. Out-of-scope automatically calls the destructor
  // for the unique_ptr, freeing the resource.

스마트 포인터에 대한 자세한 내용은 스마트 포인터를 참조 하세요.

포인터 변환에 대한 자세한 내용은 형식 변환 및 형식 안전을 참조하세요.

일반적인 포인터에 대한 자세한 내용은 포인터를 참조 하세요.

Windows 데이터 형식

C 및 C++용 클래식 Win32 프로그래밍에서 대부분의 함수는 Windows 관련 typedef 및 #define 매크로(정의 windef.h됨)를 사용하여 매개 변수 형식과 반환 값을 지정합니다. 이러한 Windows 데이터 형식은 주로 C/C++ 기본 제공 형식에 지정된 특수 이름(별칭)입니다. 이러한 typedef 및 전처리기 정의의 전체 목록은 Windows 데이터 형식을 참조 하세요. 이러한 typedef(예: HRESULTLCID)는 유용하고 설명적입니다. 같은 INT다른 항목은 특별한 의미가 없으며 기본 C++ 형식에 대한 별칭일 뿐입니다. 그 외 Windows 데이터 유형은 C 프로그래밍 및 16비트 프로세서 시기부터 내려온 이름을 그대로 가지고 있으며 최신 하드웨어 또는 운영 체제에 다른 목적과 의미를 가지고 있지 않습니다. Windows 런타임 라이브러리와 연결된 특수 데이터 형식도 Windows 런타임 기본 데이터 형식으로 나열됩니다. 최신 C++에서 일반적인 지침은 Windows 형식이 값을 해석하는 방법에 대한 추가적인 의미를 전달하지 않는 한 C++ 기본 형식을 선호하는 것입니다.

자세한 정보

C++ 형식 시스템에 대한 자세한 내용은 다음 문서를 참조하세요.

값 형식
사용과 관련된 문제와 함께 값 형식에 대해 설명합니다.

형식 변환 및 형식 안전성
일반적인 형식 변환 문제를 설명하고 이러한 문제를 방지하는 방법을 보여 줍니다.

참고 항목

C++ 시작하기
C++ 언어 참조
C++ 표준 라이브러리