(CppCon 2023) Great C++ is_trivial

写在前面

参考链接 https://www.youtube.com/watch?v=bpF1LKQBgBQ

这篇演讲有关 C++ 中的 trivial 概念。并且提到当对象 trivially copyable 时,参数传递和返回值都会变得更容易优化。

返回值优化

第 2 段代码在 C++20 之前不能被优化是因为结构化绑定的分量是结构体的一部分,作为返回值时不能被直接建在调用者的栈上。

Trivial 的概念

Note

有虚函数或者虚基类(也就是需要 vptr),就不满足平凡构造/赋值/拷贝了。如果没有给出析构函数,还是可以平凡析构的。

  • std::is_trivially_destructable
    • 空 destructor(~T() {})是不满足的。
    • = default 是满足的。
  • std::is_trivially_constructible:除了第 1 个类型参数之外,后面还能加更多参数,用来判断是否可以用给定的类型完成 trivial 构造。可以看这个例子和图 1。
    • 空 constructor 是不满足的(T() {})。
    • 成员有值初始化是不满足的(struct S { int i{}; };)。
    • 用户提供的构造函数都不适用这一点。
    • std::is_trivially_default_constructible:相当于单参数的 std::is_trivially_constructible
    • std::is_trivially_copy_constructible:限定了拷贝构造(std::is_trivially_constructible<T, const T&>)。其他条件满足时,成员有值初始化也可以(struct S { int i{}; };)。
    • std::is_trivially_move_constructible:限定了移动构造(std::is_trivially_constructible<T, T&&>)。
  • std::is_trivially_assignable:得分从哪里 assign,所以图 2 的类型 Sconst S& 是可以的,但是从 const int 就不能 trivially assign。
    • 用户提供的 assign operator 都不适用这一点。
    • 同样有 std::is_trivially_copy_assignablestd::is_trivially_move_assignable
  • std::is_trivially_copyable:字面意思是能按照字节拷贝并保持其含义,有很多条件需要满足:
    • 有一个 trivial, non-deleted destructor。
    • 至少有一个满足条件的 copy constructor, move constructor, copy assignment operator, or move assignment operator,且如果存在,它们都是 trivial 的。
  • std::is_trivial:scalar types, trivial class types, and arrays or cv-qualified versions of them. 见 TrivialType
    • trivial class types 需要满足 std::is_trivially_copyable 而且有至少 1 个的 eligible default constructors,而且这些 constructors 都是 trivial 的。

图 1:

图 2(从 const int 不是平凡赋值,从 S 是可以平凡赋值的):