Mar 9, 2014

[C++11] POD type

POD Type
Answer from stackoverflow

An aggregate is an

  • array 
  • class [i.e classes, structs, and unions] (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
i.e:
  • Can have trivial constructor (not defined by user)
  • No private or protected non-static data members.
    • Can have member function
    • Can hava static member function
  • An aggregate class can have a user-declared/user-defined copy-assignment operator and/or destructor
  • An array is an aggregate even if it is an array of non-aggregate class type.
Type array_name[n] = {a1, a2, ..., am};

if(m == n)
//the ith element of the array is initialized with ai
else if(m < n)
//the first m elements of the array are initialized with 
//a1, a2, ..., am and the other n - m elements are,
//if possible, value-initialized (see below for the explanation of the term)
else if(m > n)
//the compiler will issue an error
else //(this is the case when n isn't specified at all like int a[] = {1,2,3};)
//the size of the array (n) is assumed to be equal to m, so 
int a[] = {1,2,3} 
//is equivalent to int a[3] = {1,2,3};
class A
{
public:
  A(int){} //no default constructor
};
class B
{
public:
  B() {} //default constructor available
};
int main()
{
  A a1[3] = {A(2), A(1), A(14)}; //OK n == m
  A a2[3] = {A(2)}; //ERROR A has no default constructor. Unable to value-initialize a2[1] and a2[2]
  B b1[3] = {B()}; //OK b1[1] and b1[2] are value initialized, in this case with the default-ctor
  int Array1[1000] = {0}; //All elements are initialized with 0;
  int Array2[1000] = {1}; //Attention: only the first element is 1, the rest are 0;
  bool Array3[1000] = {}; //the braces can be empty too. All elements initialized with false
  int Array4[1000]; //no initializer. This is different from an empty {} initializer in that
  //the elements in this case are not value-initialized, but have indeterminate values 
  //(unless, of course, Array4 is a global array)
  int array[2] = {1,2,3,4}; //ERROR, too many initializers
}


A POD-struct is

  • aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference
  • has no user-defined copy assignment operator 
  • no user-defined destructor. 
  • Similarly, a POD-union is 
    • an aggregate union that has no non-static data members of type non-POD-truct, non-POD-union (or array of such types) or reference
    • has no user-defined copy assignment operator 
    • no user-defined destructor. 
  • A POD class is a class that is either a POD-struct or a POD-union.
struct POD
{
  int x;
  char y;
  void f() {} //no harm if there's a function
  static std::vector<char> v; //static members do not matter
};

struct AggregateButNotPOD1
{
  int x;
  ~AggregateButNotPOD1(){} //user-defined destructor
};

struct AggregateButNotPOD2
{
  AggregateButNotPOD1 arrOfNonPod[3]; //array of non-POD class
};


POD-classes, POD-unions, scalar types, and arrays of such types are collectively called POD-types.

  • POD-classes are the closest to C structs. 
  • Unlike C struct, POD's can have member functions and arbitrary static members, but neither of these two change the memory layout of the object. 
  • If want to write a more or less portable dynamic library that can be used from C and even .NET, should try to make all exported functions take and return only parameters of POD-types.
  • The lifetime of POD object begins when storage for the object is occupied and finishes when that storage is released or reused.
  • For objects of POD types it is guaranteed by the standard that when you memcpy the contents of object into an array of char or unsigned char, and then memcpy the contents back into object, the object will hold its original value. 
  • Do note that there is no such guarantee for objects of non-POD types. 
  • Also, we can safely copy POD objects with memcpy.
#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
memcpy(buf, &obj, N); // between these two calls to memcpy,
// obj might be modified
memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
// holds its original value


goto statement:

  • Illegal (the compiler should issue an error) to make a jump via goto from a point where some NON-POD variable was not yet in scope to a point where it is already in scope.
//ill form
int f() {
  struct NonPOD { NonPOD(){}};
  goto label;
  NonPOD x;
label:
  return 0;
}

// OK
int g(){
  struct POD {int i;  char c;};
  goto label;
  POD x;
label:
  return 0;
}

Why can't variables be declared in a switch statement?

Guaranteed that there will be no padding in the beginning of a POD object.
In other words, if a POD-class A's first member is of type T,
we can safely reinterpret_cast from A* to T* and get the pointer to the first member and vice versa.


switch (i)
{
   case 0:
     int j; // 'j' has indeterminate value
     j = 0; // 'j' initialized to 0, but this statement
            // is jumped when 'i == 1'
     break;
   case 1:
     ++j;   // 'j' is in scope here - but it has an indeterminate value
     break;
}

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.