What is POD in C++?

POD is Plain Old Data. In C++, it refers to objects that can be treated as “data only,” where programmers do not need to worry about the complexity of class layout, as well as user-defined constructors, copy, and move semantics.

Before introducing what POD is, it is essential to understand the following concepts.

Scalar types

Arithmetic types (3.9.1), enumeration types, pointer types, pointer to member types (3.9.2), std::nullptr_t, and cv-qualified versions of these types (3.9.3) are collectively called scalar types.

standard-layout types

Scalar types, standard-layout class types (Clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called standard-layout types. (ISO/IEC 14882:2014(E) §3.9.1 P71)

standard-layout class

A standard-layout class is a class that:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member. (This ensures that two subobjects that have the same class type and that belong to the same most derived object are not allocated at the same address)

In simpler terms, a type has a standard layout if it must not have the following properties:

  • Contains a non-standard layout non-static member or base class
  • Contains virtual functions
  • Contains virtual base classes
  • Contains member of reference type
  • Has non-static data members with multiple access specifiers (public/private/protected)
  • Prevents important layout optimizations
    • Contains non-static data members in multiple base classes, or contains non-static data members in both the derived class and base class
    • Has a base class type that is the same as the type of the first non-static data member

Essentially, standard-layout types are those that are compatible with C language layout and should be able to be handled by the regular C++ ABI (Application Binary Interface).

std::is_standard_layout

The standard library provides std::is_standard_layout to determine whether a type is a standard layout, defined in type_traits.

1
2
template< class T >
struct is_standard_layout;
Member constants
value [static] true if T is a standard-layout type, false otherwise
Member functions
operator bool converts the object to bool, returns value (public member function)
operator() (C++14) returns value (public member function)
Member types
Type Definition
value_type bool
type std::integral_constant<bool, value>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <type_traits>

struct A {int m;};
struct B {
int m1;
private:
int m2;
};
struct C {virtual void foo();};

int main()
{
std::cout << std::boolalpha;
std::cout << std::is_standard_layout<A>::value << '\n';
std::cout << std::is_standard_layout<B>::value << '\n';
std::cout << std::is_standard_layout<C>::value << '\n';
}

// output
true
false
false

trivially copyable types

Cv-unqualified scalar types, trivially copyable class types (Clause 9), arrays of such types, and non-volatile const-qualified versions of these types (3.9.3) are collectively called trivially copyable types. (ISO/IEC 14882:2014(E) §3.9.1 P71)

trivially copyable class

A trivially copyable class is a class that:

  • has no non-trivial copy constructors (12.8),
  • has no non-trivial move constructors (12.8),
  • has no non-trivial copy assignment operators (13.5.3, 12.8),
  • has no non-trivial move assignment operators (13.5.3, 12.8), and
  • has a trivial destructor (12.4).

A trivial class is a class that has a default constructor (12.1), has no non-trivial default constructors, and is trivially copyable. [Note: In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes. — end note] (ISO/IEC 14882:2014(E) §9 P215)

Unless a type contains non-trivial copy, move, or destructor operations internally, it is considered a trivially copyable type. Built-in type variables are all trivially copyable and have standard layout. Similarly, arrays composed of trivially copyable objects are trivially copyable, and arrays comprised of standard layout objects have standard layout.

POD types

Scalar types, POD classes (Clause 9), arrays of such types, and cv-qualified versions of these types (3.9.3) are collectively called POD types.

POD must belong to the following types of objects:

  • Standard layout types (standard-layout types)
  • Trivially copyable types (trivially copyable type)

Thus, if we want to treat an object as “data only” (POD), the object must satisfy the following conditions:

  • Does not have a complex layout (for example, contains a vptr)
  • Does not have non-standard (user-defined) copy semantics
  • Contains a most trivial (trivial) default constructor

trivial default constructor: a default constructor is trivial if it does not need to do any work (use =default if you need to define one). (TC++PL4E(E) §8.2.6 P211)

It should be noted that adding or removing non-default constructors will not affect the layout and performance (this was not the case in C++98).

A POD struct is a non-union class that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). Similarly, a POD union is a union that is both a trivial class and a standard-layout class, and has no non-static data members of type non-POD struct, non-POD union (or array of such types). A POD class is a class that is either a POD struct or a POD union. (ISO/IEC 14882:2014(E) §9.1 P216)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct N { // neither trivial nor standard-layout
int i;
int j;
virtual ~N();
};
struct T { // trivial but not standard-layout
int i;
private:
int j;
};
struct SL { // standard-layout but not trivial
int i;
int j;
~SL();
};
struct POD { // both trivial and standard-layout
int i;
int j;
};

Now consider the following code:

1
2
3
4
5
6
7
8
9
10
struct s0{}; // is POD
struct s1{int a;}; // is POD
struct s2{int a;s2(int aa):a{aa}{}}; // not a POD (no default constructor)
struct S3 { int a; S3(int aa) : a(aa) { } S3() {} }; // a POD (user-defined default constructor)
struct S4 { int a; S4(int aa) : a(aa) { } S4() = default; }; // a POD
struct S5 { virtual void f(); /*...*/ }; // not a POD (has a virtual function)
struct S6 : S1 { }; // a POD
struct S7 : S0 { int b; }; // a POD
struct S8 : S1 { int b; }; // not a POD (data in both S1 and S8)
struct S9 : S0, S1 {}; // a POD

std::is_pod

You can use std::is_pod to determine whether a type is a POD type. std::is_pod is a standard library type trait predicate defined in type_traits, with the same usage, member functions, and member types as std::is_standard_layout.

1
2
template< class T >
struct is_pod;
1
2
3
4
5
6
7
8
9
10
11
12
int main()
{
std::cout << std::boolalpha;
std::cout << std::is_pod<A>::value << '\n';
std::cout << std::is_pod<B>::value << '\n';
std::cout << std::is_pod<C>::value << '\n';
}

// output
true
false
false
The article is finished. If you have any questions, please comment and communicate.

Scan the QR code on WeChat and follow me.

Title:What is POD in C++?
Author:LIPENGZHA
Publish Date:2016/12/03 00:04
World Count:4.8k Words
Link:https://en.imzlp.com/posts/1140/
License: CC BY-NC-SA 4.0
Reprinting of the full article is prohibited.
Your donation will encourage me to keep creating!