trivial vs. standard layout vs. POD
In layman's terms, what's the difference between trivial types, standard layout types and POD开发者_高级运维s?
Specifically, I want to determine whether new T
is different from new T()
for any template parameter T
. Which of the type traits is_trivial
, is_standard_layout
and is_pod
should I choose?
(As a side question, can any of these type traits be implemented without compiler magic?)
I don't think it can be done in truly layman's terms, at least without a lot of extra explanation. One important point is static vs. dynamic initialization, but explaining that to a layman would be several pages in itself...
PODs were (mis-)defined in C++98. There are really two separate intents involved, neither expressed very well: 1) that if you compile a C struct declaration in C++, what you get should be equivalent to what you had in C. 2) A POD will only ever need/use static (not dynamic) initialization.
C++0x/11 drops the "POD" designation (almost) entirely, in favor of "trivial" and "standard layout". Standard layout is intended to capture the first intent -- creating something with a layout the same as you'd get in C. Trivial is intended to capture the support for static initialization.
Since new T
vs. new T()
deals with initialization, you probably want is_trivial
.
I'm not sure about compiler magic being required. My immediate reaction would be probably yes, but knowing some of the things people have done with TMP, I have a hard time being certain somebody couldn't do this too...
Edit: for examples, perhaps it's best to just quote the examples from N3290:
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;
};
As you can undoubtedly guess, POD
is also a POD struct.
For POD types new T()
is value-initialization(will value-initialize all members) ,and new T
will not initialize the members (default-initialization). For differences between different forms of initialization see this question. Bottom line: you need is_pod
.
Layout is how the members of an object of class, struct or a union is arranged in the memory. This may be contigious or not.Quite often the language specifies the layout , but if there are something like virtual function ,virtual base class etc , then the complier is free to choose the layout and that may not be contigiuos. This leads to several issues that we cannot serialize the object suitably or pass to programs written in other languages like C or functions like memcopy because we cannot copy the data reliably that it is not in contigious locations.
Inorder to enable the compilers and c++ programs to support the above mentioned operations c++ has introduced 3 categories for the simple structures and classes.
Trivial
A class or struct is trivial if it follows the rules:
- no virtual function or virtual base class
- no user-defined constructor/operator/destructor
- base class should be trivial
- all the class members should be trivial
If a class is trivial then its layout is contigious but there may be padding accordingly and the compiler is free to choose the order of the members in the layout. So even though we can memcopy the object it is not reliable if we copy that object to C program.We can have different access specifiers in the same class itself and if use a parameterized constructor obviously we have to specify the default contructor. But if you want to keep the class trivial then you should explicitly make the constructor default.The constructors should be public.
Standard-layout
- No virtual functions and virtual base class
- All the non-static members should have same access specifiers
- All non-static members should be of standard layout
- All base classes should be of standard layout
- All the members of the base class should be static
- The type of the base class and first non-static member of the class should not be the same
Standard layout is well defined and it can be memcopied reliably and passed to C programs suitably. Also standard layout functions can have user-defined special member funtions like constructor and destructor.
POD(Plain old data)
If a class or structure is both trivial and standard layout , then it is said to be POD.Each member is stored in the order as specified when the object is declared. POD classes should have POD non-static data members.POD classes can be copied or passed to C programs reliably.
C++ program with a class which is trivial , standard layout and therefore POD.
#include<iostream>
#include<type_traits>
class xyz
{
public:
int a;
int b;
xyz() = default;
xyz(int x, int y) :a(x), b(y) {}
};
int main() {
std::cout << std::is_trivial<xyz>() << std::endl;//true
std::cout << std::is_standard_layout<xyz>() << std::endl;//true
std::cout << std::is_pod<xyz>() << std::endl;//true
}
Literal types
For a literal type the layout can be determined at the time of compilation .Examples of literal types are void,scalar types such as int , float etc,references,Arrays of void, scalar types or references and A class that has a trivial destructor, and one or more constexpr constructors that are not move or copy constructors. Additionally, all its non-static data members and base classes must be literal types and not volatile
精彩评论