Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Standard Layout Classes and Trivially Copyable Types, Part I

Last updated Jan 1, 2003.

Traditionally, C++ distinguished between two categories of types: POD types and non-POD types. However, in some cases, this distinction is too restrictive because certain non-POD types have properties that make them behave as if they were POD types, e.g., a specified binary layout. C++11 therefore introduced new type categories: standard layout classes and trivially copyable classes. The first part of the current series will explain what standard layout classes are and how they differ from POD types.

Standard Layout Classes

Before we delve into the formal definition, let's see what standard layout types are good for. Suppose you have the following class:

class C//non-POD
{
 int x;
 int y;
public: 
 ~C();
};

Class C isn't a POD type because it has a user-declared destructor. However, its layout (binary representation in memory) is specified by the C++ standard. On the same platform and with the same default alignment, C and the following POD-struct have the same memory layout (recall that a non-virtual destructor doesn't affect the memory layout of its object):

struct C1 //POD, has the same layout as C
{
 int x;
 int y;
};

Therefore, an application written in another programming language can send and receive C objects from a C++ program.

By contrast, a non-standard layout class is one whose layout is unspecified by the C++ standard. In particular, non-standard layout classes are those that have virtual member functions, virtual base classes or data members of a non-standard layout type. Why are virtual member functions and virtual base classes crucial? In the Object Model I explained how virtual functions and virtual base classes are implemented. In brief, they both require that the implementation shall store a hidden pointer to the virtual functions table and a hidden pointer to the shared virtual base subobject inside the class object. The location of these hidden pointers is implementation-defined. Consequently, the layout of an object with such a hidden pointer is unspecified. Let's look at a concrete example:

class C2//non-POD
{
 int x;
 int y;
public: 
 virtual ~C();
};

The layout of C2 is implementation-defined. It could be identical to this struct's layout:

struct C2a //POD 
{
 void * __vptr;
 int x;
 int y;
};

Or it could be identical to this:

struct C2a //POD 
{
 int x;
 int y;
 void * __vptr;
};

Theoretically at least, the layout of C2 might even be like this:

struct C1 //POD, has the same layout as C
{
 int x;
 int y;
};

I'm not aware of any C++ implementation that doesn't store a hidden pointer to the virtual functions table inside class objects but theoretically, such implementations are possible. The bottom line is this: once you have virtual functions or virtual base classes, the layout is unspecified and therefore it's non-standard.

A Formal Definition

Informally, a standard layout class is one without direct or indirect virtual member functions, reference data members or virtual base classes. Formally, 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. In simpler words, a standard layout class shall not have reference variables as data members or member objects of a non-standard layout class.
  • Has no virtual functions and no virtual base classes.
  • Has the same access control 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.
  • Has no base classes of the same type as the first non-static data member.

The last two requirements need to be clarified. With respect to inheritance, a standard layout class can be a class with no data members of its own but with a base class that has data members, as in:

struct S
{
 int x;
};
class T : S{}; //no data members in derived. T is a standard layout class

Or it could a class that declares data members and inherits from an empty base class:

struct A {
 A(); //no data members in base
};
struct B :A{ //B is standard-layout class
 int x; 
 B();
};

However, U isn't a standard layout class:

struct U : S //both base and derived classes define data members
{
 int z; 
};

The last requirement: "a standard layout class has no base classes of the same type as the first non-static data member" also warrants an explanation. Its aim is to ensure 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, as in:

struct A{};
struct B : A //B has non-standard layout
{
 A a;
};

Standard Layout Unions

The C++11 standard also defines a standard-layout union as a standard-layout class defined with the class-key union. In other words, a union that meets the requirements of a standard layout class is a standard layout union. Since a union cannot have base classes, non-static reference data members or virtual member functions, the requirements from a standard layout union are that its members shall be of standard layout types, and that it shall not have different access types for its data members:

union X //non-standard layout

{
public:
 int x;
private:
 int y;
};

In the second part we will explore additional type categories such as trivially-copyable types and scalar types, and see how they are related to standard layout types.