拷贝不变(trivially copyable)类型

Trivial 类型

上面提到的第一个特性Trivial:trivial类型支持静态初始化。如果一个类型是拷贝不变的(trivially copyable),使用memcpy这种方式把它的数据从一个地方拷贝出来会得到相同的结果。 

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

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

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

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

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

  • 有一个trivial的析构函数

一个trivial class类型是指有一个trivial类型的默认构造函数,而且是拷贝不变的(trivially copyable)的class。(特别注意,拷贝不变类型和trivial类型都不能有虚函数和虚基类)。

那么,这么trivial和non-trivial类型到底是什么呢?

Class X复制或转移构造函数是trivial类型的,如果他不是用户提供的,而且

  • Class X没有任何虚函数和虚基类,而且
  • 用于复制或转移直接基类的构造函数是trivial类型的,而且
  • 复制或转移构造函数选择复制或转移的X内部的每一个非静态数据成员(或数组)必须是trivial类型的

否则,复制或转移构造函数就是non-trivial类型的

从根本上也就是说复制或转移构造函数是trivial类型的只要他不是用户提供的、类内部没有虚函数,而且这个规则要递归地适用于所有数据成员类型和基类。

Trivial类型赋值或转移操作符的定义类似,把构造函数替换为赋值操作符就可以了。

Trivial类型的析构函数也有类似的定义,不过要加一条限制,就是不能为虚函数。

Trivial类型的默认构造函数也需要加一条限制:上面我们已经看到了,不能拥有{ }或=初始化的(brace-or-equal-initializers)非静态数据成员。

 这里有个几个例子能让你彻底明白每个类型:

// empty classes are trivial
struct Trivial1 {};

// all special members are implicit
struct Trivial2 {
    int x;
};

struct Trivial3 : Trivial2 { // base class is trivial
    Trivial3() = default; // not a user-provided ctor
    int y;
};

struct Trivial4 {
public:
    int a;
private: // no restrictions on access modifiers
    int b;
};

struct Trivial5 {
    Trivial1 a;
    Trivial2 b;
    Trivial3 c;
    Trivial4 d;
};

struct Trivial6 {
    Trivial2 a[23];
};

struct Trivial7 {
    Trivial6 c;
    void f(); // it's okay to have non-virtual functions
};

struct Trivial8 {
    int x;
    static NonTrivial1 y; // no restrictions on static members
}

struct Trivial9 {
    Trivial9() = default; // not user-provided
    // a regular constructor is okay because we still have default ctor
    Trivial9(int x) : x(x) {};
    int x;
}

struct NonTrivial1 : Trivial 3 {
    virtual f(); // virtual members make non-trivial ctors
}

struct NonTrivial2 {
    NonTrivial2() : z(42) {} // user-provided ctor
    int z;
}

struct NonTrivial3 {
    NonTrivial3(); // user-provided ctor
    int w;
}
NonTrivial3::NonTrivial3() = default; // defaulted but not on first declaration
// still counts as user-provided
struct NonTrivial5 {
    virtual ~NonTrivial5(); // virtual destructors are not trivial
};

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值