(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
是满足的。
- 空 destructor(
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&&>
)。
- 空 constructor 是不满足的(
std::is_trivially_assignable
:得分从哪里 assign,所以图 2 的类型S
从const S&
是可以的,但是从const int
就不能 trivially assign。- 用户提供的 assign operator 都不适用这一点。
- 同样有
std::is_trivially_copy_assignable
和std::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 的。
- trivial class types 需要满足
图 1:
图 2(从 const int 不是平凡赋值,从 S 是可以平凡赋值的):