C++11 trivial, standard_layout, POD的好处和STL类型属于哪种?
C++11引进了更加完善的类型系统。包括将原本的POD类型细分为: trivial和standard_layout类型,同时具有这两个的就是POD。
trivial好处:
支持静态初始化,就是C-style array, struct和array<int>使用{}的初始化方式。注:vector等的初始化列表不属于静态初始化。
是拷贝不变的(trivially copyable)的class,可以使用memcpy, memmove不改变它的语义。
standard_layout好处:
它对语言间交互很有用,这是因为C++ standard-layout类型和C中struct或union类型有相同的内存布局。
但是,它不满足trival的两个好处。
检测:标准模板块(STL)在头文件<type_traits>中定义了对这些类型的检测
#include <type_traits>
template <typename T>
struct std::is_pod;
template <typename T>
struct std::is_trivial;
template <typename T>
struct std::is_trivially_copyable;
template <typename T>
struct std::is_standard_layout;
对C++11中一些类型的测试:windows 7 + Cygwin + gcc version 4.8.2 (GCC)
1 #include <iostream> 2 #include <list> 3 #include <deque> 4 #include <vector> 5 #include <array> 6 #include <map> 7 #include <set> 8 #include <type_traits> 9 #include <string> 10 #include <memory> 11 #include <unordered_set> 12 #include <unordered_map> 13 #include <utility> //for pair 14 15 using std::shared_ptr; 16 using std::unique_ptr; 17 using std::unordered_set; 18 using std::unordered_map; 19 using std::list; 20 //using std::is_trivially_copyable; 21 using std::deque; 22 using std::vector; 23 using std::array; 24 using std::cout; 25 using std::map; 26 using std::set; 27 using std::pair; 28 using std::endl; 29 using std::is_pod; 30 using std::is_trivial; 31 using std::is_standard_layout; 32 using std::string; 33 34 int main(void) 35 { 36 cout << "int:" << endl; 37 cout << "is_trivial: " << is_trivial<int>::value << endl; 38 cout << "is_standard_layout: " << is_standard_layout<int>::value << endl; 39 cout << "is_pod: " << is_pod<int>::value << endl << endl; 40 41 cout << "string:" << endl; 42 cout << "is_trivial: " << is_trivial<string>::value << endl; 43 cout << "is_standard_layout: " << is_standard_layout<string>::value << endl; 44 cout << "is_pod: " << is_pod<string>::value << endl; 45 cout << "sizeof(string): " << sizeof(string) << endl << endl; 46 47 cout << "array<int>:" << endl; 48 cout << "is_trivial: " << is_trivial<array<int, 5>>::value << endl; 49 cout << "is_standard_layout: " << is_standard_layout<array<int, 5>>::value << endl; 50 cout << "is_pod: " << is_pod<array<int, 5>>::value << endl << endl;; 51 52 cout << "array<string>:" << endl; 53 cout << "is_trivial: " << is_trivial<array<string, 5>>::value << endl; 54 cout << "is_standard_layout: " << is_standard_layout<array<string, 5>>::value << endl; 55 cout << "is_pod: " << is_pod<array<string, 5>>::value << endl << endl; 56 57 cout << "pair<int, int>:" << endl; 58 cout << "is_trivial: " << is_trivial<pair<int, int>>::value << endl; 59 cout << "is_standard_layout: " << is_standard_layout<pair<int, int>>::value << endl; 60 cout << "is_pod: " << is_pod<pair<int, int>>::value << endl;; 61 cout << "sizeof(pair<int, int>): " << sizeof(pair<int,int>) << endl << endl; 62 63 cout << "pair<string, string>:" << endl; 64 cout << "is_trivial: " << is_trivial<pair<string, string>>::value << endl; 65 cout << "is_standard_layout: " << is_standard_layout<pair<string, string>>::value << endl; 66 cout << "is_pod: " << is_pod<pair<string, string>>::value << endl; 67 cout << "sizeof(pair<string, string>): " << sizeof(pair<string, string>) << endl << endl; 68 69 cout << "vector<int>:" << endl; 70 cout << "is_trivial: " << is_trivial<vector<int>>::value << endl; 71 cout << "is_standard_layout: " << is_standard_layout<vector<int>>::value << endl; 72 cout << "is_pod: " << is_pod<vector<int>>::value << endl;; 73 cout << "sizeof(vector<int>): " << sizeof(vector<int>) << endl << endl; 74 75 cout << "vector<string>:" << endl; 76 cout << "is_trivial: " << is_trivial<vector<string>>::value << endl; 77 cout << "is_standard_layout: " << is_standard_layout<vector<string>>::value << endl; 78 cout << "is_pod: " << is_pod<vector<string>>::value << endl; 79 cout << "sizeof(vector<string>): " << sizeof(vector<string>) << endl << endl; 80 81 cout << "deque<int>:" << endl; 82 cout << "is_trivial: " << is_trivial<deque<int>>::value << endl; 83 cout << "is_standard_layout: " << is_standard_layout<deque<int>>::value << endl; 84 cout << "is_pod: " << is_pod<deque<int>>::value << endl;; 85 cout << "sizeof(deque<int>): " << sizeof(deque<int>) << endl << endl; 86 87 cout << "deque<string>:" << endl; 88 cout << "is_trivial: " << is_trivial<deque<string>>::value << endl; 89 cout << "is_standard_layout: " << is_standard_layout<deque<string>>::value << endl; 90 cout << "is_pod: " << is_pod<deque<string>>::value << endl; 91 cout << "sizeof(deque<string>): " << sizeof(deque<string>) << endl << endl; 92 93 cout << "list<int>:" << endl; 94 cout << "is_trivial: " << is_trivial<list<int>>::value << endl; 95 cout << "is_standard_layout: " << is_standard_layout<list<int>>::value << endl; 96 cout << "is_pod: " << is_pod<list<int>>::value << endl; 97 cout << "sizeof(list<int>): " << sizeof(list<int>) << endl << endl; 98 99 cout << "list<string>:" << endl; 100 cout << "is_trivial: " << is_trivial<list<string>>::value << endl; 101 cout << "is_standard_layout: " << is_standard_layout<list<string>>::value << endl; 102 cout << "is_pod: " << is_pod<list<string>>::value << endl; 103 cout << "sizeof(list<string>): " << sizeof(list<string>) << endl << endl; 104 105 cout << "vector<list<int>>:" << endl; 106 cout << "is_trivial: " << is_trivial<vector<list<int>>>::value << endl; 107 cout << "is_standard_layout: " << is_standard_layout<vector<list<int>>>::value << endl; 108 cout << "is_pod: " << is_pod<vector<list<int>>>::value << endl; 109 cout << "sizeof(vector<list<int>>): " << sizeof(vector<list<int>>) << endl << endl; 110 111 cout << "vector<list<string>>:" << endl; 112 cout << "is_trivial: " << is_trivial<vector<list<string>>>::value << endl; 113 cout << "is_standard_layout: " << is_standard_layout<vector<list<string>>>::value << endl; 114 cout << "is_pod: " << is_pod<vector<list<string>>>::value << endl; 115 cout << "sizeof(vector<list<string>>): " << sizeof(vector<list<string>>) << endl << endl; 116 117 cout << "set<int>:" << endl; 118 cout << "is_trivial: " << is_trivial<set<int>>::value << endl; 119 cout << "is_standard_layout: " << is_standard_layout<set<int>>::value << endl; 120 cout << "is_pod: " << is_pod<set<int>>::value << endl; 121 cout << "sizeof(set<int>): " << sizeof(set<int>) << endl << endl; 122 123 cout << "set<string>:" << endl; 124 cout << "is_trivial: " << is_trivial<set<string>>::value << endl; 125 cout << "is_standard_layout: " << is_standard_layout<set<string>>::value << endl; 126 cout << "is_pod: " << is_pod<set<string>>::value << endl; 127 cout << "sizeof(set<string>): " << sizeof(set<string>) << endl << endl; 128 129 cout << "map<int, int>:" << endl; 130 cout << "is_trivial: " << is_trivial<map<int, int>>::value << endl; 131 cout << "is_standard_layout: " << is_standard_layout<map<int, int>>::value << endl; 132 cout << "is_pod: " << is_pod<map<int, int>>::value << endl; 133 cout << "sizeof(map<int, int>): " << sizeof(map<int, int>) << endl << endl; 134 135 cout << "map<string, string>:" << endl; 136 cout << "is_trivial: " << is_trivial<map<string, string>>::value << endl; 137 cout << "is_standard_layout: " << is_standard_layout<map<string, string>>::value << endl; 138 cout << "is_pod: " << is_pod<map<string, string>>::value << endl; 139 cout << "sizeof(map<string, string>): " << sizeof(map<string, string>) << endl << endl; 140 141 cout << "unordered_set<int>:" << endl; 142 cout << "is_trivial: " << is_trivial<unordered_set<int>>::value << endl; 143 cout << "is_standard_layout: " << is_standard_layout<unordered_set<int>>::value << endl; 144 cout << "is_pod: " << is_pod<unordered_set<int>>::value << endl; 145 cout << "sizeof(unorder_set<int>): " << sizeof(unordered_set<int>) << endl << endl; 146 147 cout << "unordered_set<string>:" << endl; 148 cout << "is_trivial: " << is_trivial<unordered_set<string>>::value << endl; 149 cout << "is_standard_layout: " << is_standard_layout<unordered_set<string>>::value << endl; 150 cout << "is_pod: " << is_pod<unordered_set<string>>::value << endl; 151 cout << "sizeof(unorder_set<string>): " << sizeof(unordered_set<string>) << endl << endl; 152 153 154 cout << "unordered_map<int, int>:" << endl; 155 cout << "is_trivial: " << is_trivial<unordered_map<int, int>>::value << endl; 156 cout << "is_standard_layout: " << is_standard_layout<unordered_map<int, int>>::value << endl; 157 cout << "is_pod: " << is_pod<unordered_map<int, int>>::value << endl; 158 cout << "sizeof(unorder_map<int, int>): " << sizeof(unordered_map<int, int>) << endl << endl; 159 160 cout << "unordered_map<string, string>:" << endl; 161 cout << "is_trivial: " << is_trivial<unordered_map<string, string>>::value << endl; 162 cout << "is_standard_layout: " << is_standard_layout<unordered_map<string, string>>::value << endl; 163 cout << "is_pod: " << is_pod<unordered_map<string, string>>::value << endl; 164 cout << "sizeof(unorder_map<string, string>): " << sizeof(unordered_map<string, string>) << endl << endl; 165 166 cout << "shared_ptr<int>:" << endl; 167 cout << "is_trivial: " << is_trivial<shared_ptr<int>>::value << endl; 168 cout << "is_standard_layout: " << is_standard_layout<shared_ptr<int>>::value << endl; 169 cout << "is_pod: " << is_pod<shared_ptr<int>>::value << endl; 170 cout << "sizeof(shared_ptr<int>): " << sizeof(shared_ptr<int>) << endl << endl; 171 172 cout << "unique_ptr<int>:" << endl; 173 cout << "is_trivial: " << is_trivial<unique_ptr<int>>::value << endl; 174 cout << "is_standard_layout: " << is_standard_layout<unique_ptr<int>>::value << endl; 175 cout << "is_pod: " << is_pod<unique_ptr<int>>::value << endl; 176 cout << "sizeof(unique_ptr<int>): " << sizeof(unique_ptr<int>) << endl << endl; 177 178 return 0; 179 }
程序输出:
int: is_trivial: 1 is_standard_layout: 1 is_pod: 1
string: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(string): 4
array<int>: is_trivial: 1 is_standard_layout: 1 is_pod: 1
array<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0
pair<int, int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(pair<int, int>): 8
pair<string, string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(pair<string, string>): 8
vector<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(vector<int>): 12
vector<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(vector<string>): 12
deque<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(deque<int>): 40
deque<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(deque<string>): 40
list<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(list<int>): 8
list<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(list<string>): 8
vector<list<int>>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(vector<list<int>>): 12
vector<list<string>>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(vector<list<string>>): 12
set<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(set<int>): 24
set<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(set<string>): 24
map<int, int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(map<int, int>): 24
map<string, string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(map<string, string>): 24
unordered_set<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(unorder_set<int>): 24
unordered_set<string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(unorder_set<string>): 24
unordered_map<int, int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(unorder_map<int, int>): 24
unordered_map<string, string>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(unorder_map<string, string>): 24
shared_ptr<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(shared_ptr<int>): 8
unique_ptr<int>: is_trivial: 0 is_standard_layout: 1 is_pod: 0 sizeof(unique_ptr<int>): 4
结论:内置类型(如: int, float),array<int>是POD类型
POD类型是递归的,array<string>就不是POD类型,因为string不是
所有测试类型包括:pair(tuple), vector, list, deque, set, map, unordered_set, unordered_map, shared_ptr, unique_ptr
都满足 is_standard_layout但是不满足is_trivial,因此也不满足is_pod类型。
unique_ptr具有和普通指针一样大小,大多数时候应该使用它(当然还有其它原因: 如unique性能更好等等),而不是shared_ptr。