为什么类可以轻松复制所有私有特殊成员函数?

o_o*_*tle 14 c++ language-lawyer c++20 trivially-copyable

代码如下:

#include <iostream>
#include <type_traits>

class A
{
    A() = default;
    A(const A&) = default;
    A(A&&) = default;
    A& operator=(const A&) = default;
    A& operator=(A&&) = default;
    ~A() = default;
    int a;
};

int main()
{
    std::cout << std::boolalpha <<
        std::is_trivially_copy_assignable_v<A> << " " <<
        std::is_trivially_copy_constructible_v<A> << " " <<
        std::is_trivially_move_assignable_v<A> << " " <<
        std::is_trivially_move_constructible_v<A> << " " <<
        std::is_trivially_destructible_v<A> << " " <<
        std::is_trivially_copyable_v<A> << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

And the output is false false false false false true. But according to cppreference:

A trivially copyable class is a class that

  • has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator,
  • each eligible copy constructor is trivial
  • each eligible move constructor is trivial
  • each eligible copy assignment operator is trivial
  • each eligible move assignment operator is trivial, and
  • has a non-deleted trivial destructor.

So from the first four boolean outputs, none of the copy constructor, move constructor, copy assignment operator and move assignment operator is trivial, so it's supposed to be non-trivially-copyable; However, the last output boolean is true.

Note: You can make ~A() = default and A() = default public so that you can create objects, but the core question is still the same.

And*_*ent 18

问题不是这个类的实例实际上可以被复制吗?

std::is_trivially_copyable答案

如果您使用字节复制来复制此实例,结果是否与使用复制运算符进行复制相同


use*_*522 10

std::is_trivially_copy_constructible_v<T>不检查是否T有一个简单的复制构造函数,这是trivially-copyable所基于的。

相反,它检查是否存在以下形式的变量的定义

T t(u);
Run Code Online (Sandbox Code Playgroud)

其中u是 类型的变量const T,在与 无关的上下文中将是格式良好的T,并且该变量的构造将仅使用简单的函数。这包括对可访问性的检查和对未删除的可访问析构函数的检查。

这同样以类似的形式适用于其他_constructible__assignable_特征。这些特征与 没有直接关系is_trivially_copyable。该is_trivially_copyable特征告诉您是否可以用来memcpy复制该类型的对象。它不会告诉您复制/移动构造/赋值是否可能且微不足道,而这正是其他特征的用途。