标签: 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 …

c++ language-lawyer c++20 trivially-copyable

14
推荐指数
2
解决办法
1357
查看次数

为什么微不足道的复制/移动可构造性取决于微不足道的可破坏性?

除了非平凡的析构函数之外,所有特殊函数都默认的类不是可简单移动或复制构造的。有关示例,请参见https://godbolt.org/z/o83rPz

#include <type_traits>

class Sample
{
public:
        Sample(Sample const&) = default;
        Sample(Sample&&) = default;
        Sample& operator=(Sample const&) = default;
        Sample& operator=(Sample&&) = default;
        ~Sample() {}
};

static_assert(std::is_copy_constructible<Sample>::value, "");
static_assert(std::is_move_constructible<Sample>::value, "");
static_assert(std::is_trivially_copy_constructible<Sample>::value, ""); // Fails with GCC and Clang
static_assert(std::is_trivially_move_constructible<Sample>::value, ""); // Fails with GCC and Clang
static_assert(std::is_copy_assignable<Sample>::value, "");
static_assert(std::is_move_assignable<Sample>::value, "");
static_assert(std::is_trivially_copy_assignable<Sample>::value, "");
static_assert(std::is_trivially_move_assignable<Sample>::value, "");
Run Code Online (Sandbox Code Playgroud)

GCC 和 Clang 都没有通过相应的断言,而 ICC 通过。奇怪的是,分配没有受到影响,尽管我可以理解分配给的对象需要被销毁。但反过来说似乎是对的。为什么?为什么ICC不同意?

c++ c++11 trivially-copyable

7
推荐指数
1
解决办法
94
查看次数

简单可复制的类 - C++20 中发生了什么变化?

标准说

一个普通可复制的类是一个类:

(1.1) 至少有一个合格的复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符([special]、[class.copy.ctor]、[class.copy.assign]),

(1.2) 其中每个合格的复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符都是微不足道的,并且

(1.3) 有一个简单的、未删除的析构函数 ([class.dtor])。

现在,我不完全确定这意味着什么。是否意味着拥有其中之一就足够了?例如,一个具有简单复制构造函数和复制赋值运算符以及显式删除的移动构造函数和移动赋值运算符的类是可以简单复制的,或者这意味着我有未删除的“big 6”并且它们中的每一个都是平凡的?

如果我从字面上理解这一点,那么只有一个构造函数或赋值运算符就足够了。根据cppreference在 c++20 之前就是这种情况。如果没有任何改变(即我仍然可以删除赋值运算符或构造函数),为什么措辞会改变?pre c++20 和 C++20 标准含义有什么区别?

更新

实验(例如Spencer 答案中的实验)表明我的猜测是正确的。我不明白的是 - 为什么要改变 C++20 标准中的措辞。实际上有什么改变吗?

c++17 定义的链接。

在 c++17 中,定义是:

  1. 一个普通可复制的类是一个类:

(6.1) 其中每个复制构造函数、移动构造函数、复制赋值运算符和移动赋值运算符 ([class.copy], [over.ass]) 要么被删除,要么被忽略,

(6.2) 具有至少一个非删除的复制构造函数、移动构造函数、复制赋值运算符或移动赋值运算符,并且

(6.3) 有一个简单的、未删除的析构函数。

旧定义和新定义之间是否存在细微差别?

c++ c++20 trivially-copyable

6
推荐指数
1
解决办法
897
查看次数

可变数据成员、模板构造函数和普通复制构造函数

示例代码可以在下面或godbolt上找到。假设我们有 4 个班级:

  1. S<T>:持有数据成员。

  2. SCtor<T>:持有数据成员并具有模板构造函数。

  3. SCtorMutable<T>:持有可变数据成员并具有模板构造函数。

  4. SCtorDefault<T>:持有一个成员,有一个模板构造函数,有默认的复制/移动构造函数和默认的复制/移动赋值运算符。

所有编译器都同意这 4 个类是可以简单复制的。

如果有一个简单的包装类W<T>将上述任何一个类作为数据成员。包装类W<S...<T>>仍然是可简单复制的。

如果有另一个包装类WMutable<T>将上述类中的任何一个保存为可变数据成员。

  1. MSVC 仍然认为WMutable<S...<T>>是可以简单复制的。
  2. clang 认为WMutable<S<T>>是可以复制的。WMutable<SCtor...<T>>不是可简单复制构造的,因此也不是可简单复制的。
  3. gcc 认为WMutable<S<T>>是可以简单复制的。WMutable<SCtor...<T>>不是可简单复制构造的,而是可简单复制的。

应该WMutable<T>是可以简单复制的吗?

#include <type_traits>
#include <utility>

template<typename T>
struct S {
    T m_t;
};

template<typename T>
struct SCtor {
    T m_t;
    template<typename... U>
    SCtor(U&&... u): m_t(std::forward<U>(u)...) {}
};

template<typename T>
struct SCtorMutable {
    mutable T m_t;
    template<typename... U> …
Run Code Online (Sandbox Code Playgroud)

c++ mutable copy-constructor language-lawyer trivially-copyable

6
推荐指数
1
解决办法
182
查看次数

适用于“memcpy()”的相同简单复制限制是否也适用于“std::copy()”?

Cppreference 指出,关于std::memcpy()(强调):

如果对象可能重叠或不可平凡复制,则 的行为memcpy 未指定并且可能未定义。

因此,我总是在使用之前检查以确保对象是可简单复制的memcpy(),如下所示:

#include <type_traits>

static_assert(std::is_trivially_copyable<T>::value, "Type T must "
    "be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
    "to use on it.");
memcpy(&outputData, &data, sizeof(data));
Run Code Online (Sandbox Code Playgroud)

std::copy()然而,似乎没有这个限制:https://en.cppreference.com/w/cpp/algorithm/copy

类型必须可简单复制才能不具有未定义行为的限制是否不适用于std::copy()

另外,我刚刚在我的“placement new”答案中意识到,这让我想知道整个事情,我只是用了memcpy()代替std::memcpy(),而我没有 using namespace std;那么调用了哪个函数?是memcpy()与 不同的实现吗std::memcpy()

c++ memcpy undefined-behavior trivially-copyable

0
推荐指数
1
解决办法
269
查看次数