Outdated/Core Language

[C++ Core] POD(plain old data), 표준 레이아웃 타입(standard layout type), 간단한 타입(trivial type)

해달 2018. 8. 17. 12:30

[C++ Core] POD(plain old data), 표준 레이아웃 타입(standard layout type), 간단한 타입(trivial type)

POD

POD(plain old data)란, 메모리 상에서 연속적인 바이트 열을 말한다. 이따금씩 개체를 POD로 취급해야 할 때가 있다. 가령 실행 시간 다형성이나 유저가 정의한 복사 의미론 등과 같은 진보된 의미론 문법이 필요없을 때말이다. 왜냐하면, POD로 취급하면 하드웨어에서 좀 더 효율적으로 개체를 옮기거나 복사할 수 있기 때문이다. 즉, POD는 클래스 레이아웃이나 유저가 정의한 생성, 복사, 이동 의미론의 복잡성에 대한 고려 없이 '데이터 자체'로 취급할 수 있는 개체이다.

POD 개체는 다음 조건을 갖춰야 한다.

  1. 표준 레이아웃 타입(standard layout type)이어야 한다.
  2. 간단한 타입(trivial type)이어야 한다.

우선 저것들이 의미하는 게 무엇인지 살펴보자.

표준 레이아웃 타입

기본적으로, 표준 레이아웃 타입(standard layout type)은 C와 분명하게 같은 레이아웃을 갖고 있는 타입이며, 공통 C++ ABIs(Apllication Binary Interfaces)가 다룰 수 있는 타입이다.

자세하게는 다음의 특성을 가진다.

  1. 가상 함수나 가상 기저 클래스를 갖지 않는다.
  2. 비정적 데이터 멤버가 동일한 접근 제어를 가진다.
  3. 모든 비정적 데이터 멤버가 표준 레이아웃이다.
  4. 모든 기저 클래스가 표준 레이아웃이다.
  5. 첫번째 비정적 멤버로 기저 클래스와 동일한 타입의 데이터를 갖지 않는다.
  6. 레퍼런스 멤버를 갖지 않는다.
  7. 한 개 이상의 기저 클래스 혹은 파생 및 기저 클래스 둘 다에서 비정적 데이터를 갖지 않는다.

좀 더 간단하게 살펴보려면 <type_traits> std::is_standard_layout을 이용하면 된다.

간단한 타입

간단한 타입(trivial type)은 (1)간단한 기본 생성자 및 소멸자와 (2)간단한 복사 및 이동 연산을 갖고 있는 타입이다. 다르게 말하면, 비트 단위 연산들이 가능하면 된다.

복사, 이동, 소멸자가 간단하지 않은 경우는 다음과 같다.

  1. 유저가 정의한 것이다.
  2. 그 클래스가 가상 함수를 가진다.
  3. 그 클래스가 가상 기저 클래스를 가진다.
  4. 그 클래스가 간단하지 않은 멤버나 기저 클래스를 가진다.

위와 마찬가지로 <type_traits> std::is_trivial을 이용하면 쉽게 확인할 수 있다.

참고로 내장 타입 개체는 표준 레이아웃을 가지며, 간단한 타입이다. 물론, 이런 타입들의 배열도 마찬가지이다.

다시 POD

POD가 될 수 있는 조건을 좀 더 쉽게 풀어보자.

  1. 복잡한 레이아웃을 갖지 않는다.(가상 함수 등)
  2. 유저가 정의한 복사 의미론을 갖지 않는다.
  3. 간단한 기본 생성자를 갖고 있다.

또한, C++11부터는 기본이 아닌 생성자를 추가하거나 빼는 것이 레이아웃이나 성능에 영향을 주지 않는다.

예시를 보자.

struct S0 { }; // POD
struct S1 { int i; }; // POD
struct S2 { int i; S2(int ii) : i(ii) { } }; // 기본 생성자가 없으므로 POD가 아니다
struct S3 { int i; S3(int ii) : i(ii) { } S3() {} }; // POD
struct S4 { int i; S4(int ii) : i(ii) { } S4() = default; }; // POD
struct S5 { virtual void f(); }; // 가상 함수가 있으므로 POD가 아니다

struct S6 : S1 { }; // POD
struct S7 : S0 { int b; } // POD
struct S8 : S1 { int b; } // 기저 클래스에 비정적 멤버가 있으므로 POD가 아니다.
struct S9 : S0, S1 { }; // POD

마찬가지로 <type_traits> std::is_pod를 이용하면 쉽게 알 수 있다.