C++中的Trivial 、POD、non-POD和Standard Layout概念

来源:互联网 发布:sql日期相减 编辑:程序博客网 时间:2024/04/27 17:29
POD types
non-POD types
Standard Layout types


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.

standard-layout 类型的类是指:

  • 没有 non-standard-layout类型(或这些类型的数组)和引用的非静态数据成员
  • 没有虚函数和虚基类

  • 非静态数据成员的访问控制必须是相同的
  • 没有non-standard-layout的基类
  • 在最底层的派生类中没有非静态数据成员,而且在最多有一个基类拥有非静态数据成员,或者没有拥有非静态数据成员

  • 相同基类类型的非静态数据成员不能作为第一个成员

C++标准把trivial类型定义如下:

一个拷贝不变(trivially copyable)类型是指:

  • 没有non-trivial 的复制构造函数

  • 没有non-trivial的转移构造函数

  • 没有non-trivial的赋值操作符
  • 没有non-trivial的转移赋值操作符

  • 有一个trivial的析构函数

更多请参考:


点击(此处)折叠或打开

  1. struct N { // neither trivial nor standard-layout
  2.    int i;
  3.    int j;
  4.    virtual ~N();
  5. };
  6. // 有一个虚拟函数就不是trivial和standard-layout

  7. struct T { // trivial but not standard-layout
  8.     int i;
  9. private:
  10.     int j;
  11. };
  12. // 数据成员访问类型不同就不是standard-layout,但可以是trivial

  13. struct SL { // standard-layout but not trivial
  14.     int i;
  15.     int j;
  16.     ~SL();
  17. };
  18. // 有非虚拟的析构或非默认的构造函数,就不是trivial,但可以是standard-layout

  19. struct POD { // both trivial and standard-layout
  20.     int i;
  21.     int j;
  22. };
這裏有個幾個例子能讓你彻底明白每個trivial類型:

点击(此处)折叠或打开

  1. 1 // empty classes are trivial
  2.  2 struct Trivial1 {};
  3.  3
  4.  4 // all special members are implicit
  5.  5 struct Trivial2 {
  6.  6 int x;
  7.  7 };
  8.  8
  9.  9 struct Trivial3 : Trivial2 { // base class is trivial
  10. 10 Trivial3() = default; // not a user-provided ctor
  11. 11 int y;
  12. 12 };
  13. 13
  14. 14 struct Trivial4 {
  15. 15 public:
  16. 16 int a;
  17. 17 private: // no restrictions on access modifiers
  18. 18 int b;
  19. 19 };
  20. 20
  21. 21 struct Trivial5 {
  22. 22 Trivial1 a;
  23. 23 Trivial2 b;
  24. 24 Trivial3 c;
  25. 25 Trivial4 d;
  26. 26 };
  27. 27
  28. 28 struct Trivial6 {
  29. 29 Trivial2 a[23];
  30. 30 };
  31. 31
  32. 32 struct Trivial7 {
  33. 33 Trivial6 c;
  34. 34 void f(); // it's okay to have non-virtual functions
  35. 35 };
  36. 36
  37. 37 struct Trivial8 {
  38. 38 int x;
  39. 39 static NonTrivial1 y; // no restrictions on static members
  40. 40 }
  41. 41
  42. 42 struct Trivial9 {
  43. 43 Trivial9() = default; // not user-provided
  44. 44 // a regular constructor is okay because we still have default ctor
  45. 45 Trivial9(int x) : x(x) {};
  46. 46 int x;
  47. 47 }
  48. 48
  49. 49 struct NonTrivial1 : Trivial 3 {
  50. 50 virtual f(); // virtual members make non-trivial ctors
  51. 51 }
  52. 52
  53. 53 struct NonTrivial2 {
  54. 54 NonTrivial2() : z(42) {} // user-provided ctor
  55. 55 int z;
  56. 56 }
  57. 57
  58. 58 struct NonTrivial3 {
  59. 59 NonTrivial3(); // user-provided ctor
  60. 60 int w;
  61. 61 }
  62. 62 NonTrivial3::NonTrivial3() = default; // defaulted but not on first declaration
  63. 63 // still counts as user-provided
  64. 64 struct NonTrivial5 {
  65. 65 virtual ~NonTrivial5(); // virtual destructors are not trivial
  66. 66 };

這裏有個幾個例子能讓你彻底明白每個standard-layout類型:

点击(此处)折叠或打开

  1. 1 // empty classes have standard-layout
  2.  2 struct StandardLayout1 {};
  3.  3
  4.  4 struct StandardLayout2 {
  5.  5 int x;
  6.  6 };
  7.  7
  8.  8 struct StandardLayout3 {
  9.  9 private: // both are private, so it's ok
  10. 10 int x;
  11. 11 int y;
  12. 12 };
  13. 13
  14. 14 struct StandardLayout4 : StandardLayout1 {
  15. 15 int x;
  16. 16 int y;
  17. 17
  18. 18 void f(); // perfectly fine to have non-virtual functions
  19. 19 };
  20. 20
  21. 21 struct StandardLayout5 : StandardLayout1 {
  22. 22 int x;
  23. 23 StandardLayout1 y; // can have members of base type if they're not the first
  24. 24 };
  25. 25
  26. 26 struct StandardLayout6 : StandardLayout1, StandardLayout5 {
  27. 27 // can use multiple inheritance as long only
  28. 28 // one class in the hierarchy has non-static data members
  29. 29 };
  30. 30
  31. 31 struct StandardLayout7 {
  32. 32 int x;
  33. 33 int y;
  34. 34 StandardLayout7(int x, int y) : x(x), y(y) {} // user-provided ctors are ok
  35. 35 };
  36. 36
  37. 37 struct StandardLayout8 {
  38. 38 public:
  39. 39 StandardLayout8(int x) : x(x) {} // user-provided ctors are ok
  40. 40 // ok to have non-static data members and other members with different access
  41. 41 private:
  42. 42 int x;
  43. 43 };
  44. 44
  45. 45 struct StandardLayout9 {
  46. 46 int x;
  47. 47 static NonStandardLayout1 y; // no restrictions on static members
  48. 48 };
  49. 49
  50. 50 struct NonStandardLayout1 {
  51. 51 virtual f(); // cannot have virtual functions
  52. 52 };
  53. 53
  54. 54 struct NonStandardLayout2 {
  55. 55 NonStandardLayout1 X; // has non-standard-layout member
  56. 56 };
  57. 57
  58. 58 struct NonStandardLayout3 : StandardLayout1 {
  59. 59 StandardLayout1 x; // first member cannot be of the same type as base
  60. 60 };
  61. 61
  62. 62 struct NonStandardLayout4 : StandardLayout3 {
  63. 63 int z; // more than one class has non-static data members
  64. 64 };
  65. 65
  66. 66 struct NonStandardLayout5 : NonStandardLayout3 {}; // has a non-standard-layout base class


結論:

在新的標准下,很多新類型成为POD類型,而且,就算一個類型不是POD類型,我們也可以分別利用POD類型的特性(只要這個類型是trivial或者standard-layout)。

標准模板塊(STL)在頭文件<type_traits>中定義了對這些類型的檢測:

1 template <typename T> 2 struct std::is_pod; 3 template <typename T> 4 struct std::is_trivial; 5 template <typename T> 6 struct std::is_trivially_copyable; 7 template <typename T> 8 struct std::is_standard_layout;

原文:




阅读(386) | 评论(0) | 转发(1) |
0

上一篇:编译错误:stray ‘\357’ in program的解决方法

下一篇:求职简历撰写要点和模板分享

相关热门文章
  • test123
  • 编写安全代码——小心有符号数...
  • 使用openssl api进行加密解密...
  • 一段自己打印自己的c程序...
  • sql relay的c++接口
  • 我的ChinaUnix博客被锁定了,...
  • 虚拟机中ubuntu无线连接问题...
  • IBM DS3400 盘阵怎么查看是单...
  • 启动auditd时,报错如下,怎么...
  • CGSL系统中root密码正确,但无...
给主人留下些什么吧!~~