тривиально-копируемый-присваиваемый против тривиально-копируемого - PullRequest
1 голос
/ 18 июня 2020

Рассмотрим следующий код. Его можно скомпилировать как с Clang, так и с G CC. Однако G CC выдает предупреждение:

warning: 'void * memcpy (void *, const void *, size_t)' записывается в объект нетривиально копируемого типа 'struct Value' ; вместо этого используйте присваивание копирования или инициализацию копирования [-Wclass-memaccess]

#include <cstring>
#include <iostream>
#include <type_traits>

static unsigned cnt2 = 0;

struct Value {
  Value(int v) noexcept : v(v), m(v+1) { }
 ~Value()      noexcept { cnt2++; }
  int v; 
  int m; 
};

static_assert(std::is_trivially_copy_assignable_v<Value>);

void copy(Value* dst, Value const* src, std::size_t len) {
  std::memcpy(dst,src,sizeof(Value)*len); }

int main() { std::cout << "Hello\n"; }

Здесь есть как минимум две проблемы.

  1. Оба компилятора прошли проверку std::is_trivially_copy_assignable_v<Value> . Так в чем разница между тривиально копируемыми присваиваемыми и тривиально копируемыми типами?
  2. Я думаю, что предупреждение правильное. Потому что деструктор Value нетривиален. Значит ли это, что для использования std::memcpy мы должны проверить и std::is_trivially_copy_assignable_v<Value>, и std::is_trivially_destructible_v<Value>?

1 Ответ

0 голосов
/ 18 июня 2020

Оба компилятора передают std::is_trivially_copy_assignable_v<Value>. Итак, в чем разница между типами с возможностью простого копирования и с возможностью простого копирования ?

Trivially-copy-assignable требует только операций с копирование-присваивание будет тривиальным. У вас может быть класс, который можно легко копировать, например, с нетривиальным деструктором или конструктором перемещения. Такой класс не будет тривиально скопирован .

Я думаю, что предупреждение правильное. Потому что деструктор Value нетривиален. Значит ли это, что для использования std::memcpy мы должны проверить как std::is_trivially_copy_assignable_v<Value>, так и std::is_trivially_destructible_v<Value>?

Я считаю, что вам нужно только проверить std::is_trivially_copyable_v<Value>. Обе проверки не дают требуемой гарантии, поскольку ваш класс все еще может иметь, например, нетривиальный конструктор перемещения, и, следовательно, его нельзя будет легко копировать и, следовательно, нельзя будет использовать с memcpy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...