std::is_trivially_assignable 是类型特性,检查 T t; t = u; 是否能以位复制方式平凡赋值,要求 T 和 U 均为平凡可复制且 T 的赋值操作不调用用户定义函数、构造/析构或涉及虚函数。

std::is_trivially_assignable 是什么,它到底检查什么
std::is_trivially_assignable 是一个类型特性(type trait),用于在编译期判断某个类型是否能通过“平凡赋值”(trivial assignment)完成赋值操作。它不检查逻辑是否安全,也不管你有没有重载 operator=;它只看编译器能否直接按字节复制(bitwise copy)——也就是不调用任何用户定义的赋值运算符、不触发构造/析构、不涉及虚函数或非平凡成员的赋值。
典型误用是把它当“是否可赋值”或“是否线程安全”的替代品。它返回 true 仅当:T 和 U 都是 trivially copyable,且 T 的默认赋值行为(隐式生成或 = default)是 trivial 的。
怎么写正确的 std::is_trivially_assignable 检查表达式
它的模板参数顺序容易搞反:std::is_trivially_assignable<t u>::value</t> 表示 “U 能否被平凡地赋给 T”,即等价于 T t; t = u; 这一语句是否触发平凡赋值。
-
std::is_trivially_assignable<int double>::value</int>→true(double可隐式转为int,且int的赋值是平凡的) -
std::is_trivially_assignable<:string const char>::value</:string>→false(std::string的赋值会调用构造/内存分配,非平凡) -
std::is_trivially_assignable<const int>::value</const>→false(const int不可被赋值,平凡性前提都不满足)
注意:C++17 起推荐用 std::is_trivially_assignable_v<t u></t> 替代 ::value 后缀,更简洁。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
为什么 std::is_trivially_assignable 在 memcpy 场景下关键
当你想用 memcpy 或 std::copy 批量复制对象时,必须确保类型是 trivially assignable(且 trivially copyable)。否则行为未定义 —— 即使代码编译通过,也可能踩内存、跳过析构、破坏 vptr。
- 结构体含
std::vector成员?std::is_trivially_assignable_v<mystruct mystruct></mystruct>一定是false - 纯 POD 结构(如
struct Point { float x,y; };)?通常是true,但若加了constexpr Point() = default;仍保持 trivial,加了~Point()就不是了 - 继承链中有虚函数?即使子类没定义新成员,
std::is_trivially_assignable_v也会是false,因为 vptr 不允许简单 memcpy
别只看类定义表面;用 static_assert 锁死条件:
static_assert(std::is_trivially_assignable_v<MyType, MyType>, "MyType must be trivially assignable for bulk memcpy");
常见陷阱:和 std::is_assignable、std::is_copy_assignable 混用
std::is_assignable 只检查语法是否合法(能不能写 t = u;),不管是不是平凡;std::is_copy_assignable 等价于 std::is_assignable<t t></t>,也完全不保证平凡性。
-
std::is_assignable<:string const char>::value</:string>→true(有string::operator=(const char*)) -
std::is_trivially_assignable<:string const char>::value</:string>→false(该 operator= 显式定义,非平凡) - 自定义类中写了
MyClass& operator=(const MyClass&) = default;?只要所有成员都 trivial,就是true;但若其中某个成员是std::mutex,则整个类立刻变成 non-trivial
真正需要“零开销赋值”的场景(比如 SIMD 对齐数组、共享内存结构体),必须盯紧 std::is_trivially_assignable_v,而不是退而求其次用 std::is_assignable。
它不报运行时错误,也不会提醒你忘了删掉一个 virtual 析构函数 —— 编译期就靠你主动查、主动锁、主动验证。

















