Подтвердить что ты не робот

Когда тип С++ 11 разрешен для memcpyed?

Мой вопрос следующий:

Если я хочу скопировать тип класса, memcpy может сделать это очень быстро. Это разрешено в некоторых ситуациях.

У нас есть некоторые черты типа:

  • is_standard_layout.
  • is_trivially_copyable.

То, что я хотел бы знать, - это точные требования, когда тип будет "побитовым".

Мое заключение состоит в том, что тип побитовоспособен, если оба свойства is_trivally_copyable и is_standard_layout верны:

  • Это именно то, что мне нужно побитовое копирование?
  • Является ли это чрезмерным?
  • Недостаточно ли это?

P.S.: Конечно, результат memcpy должен быть правильным. Я знаю, что я мог бы memcpy в любой ситуации, но неправильно.

4b9b3361

Ответ 1

Вы можете скопировать объект типа T, используя memcpy, когда is_trivally_copyable<T>::value - true. Нет особой необходимости в том, чтобы тип был стандартным типом макета. Определение "тривиально скопируемое" по существу состоит в том, что это безопасно для этого.

Пример класса, который можно скопировать с помощью memcpy, но который не является стандартным расположением:

struct T {
  int i;
private:
  int j;
};

Поскольку этот класс использует различный контроль доступа для разных нестатических элементов данных, он не является стандартным макетом, но он все еще можно копировать тривиально.

Ответ 2

Из http://en.cppreference.com/w/cpp/types/is_trivially_copyable:

Объекты тривиально-скопируемых типов являются единственными объектами С++, которые можно безопасно скопировать с помощью std::memcpy или сериализовать в/из двоичных файлов с помощью std::ofstream::write()/std::ifstream::read(). В общем случае тривиально-копируемый тип - это любой тип, для которого базовые байты могут быть скопированы в массив из char или unsigned char и в новый объект того же типа, и полученный объект будет иметь то же значение, что и оригинал.

Ответ 3

Если is_trivally_copyable<T>::value (или в С++ 14 is_trivially_copyable<T>()) не равно нулю, тип можно копировать с помощью memcpy.

В стандарте С++ тип, который тривиально копируется, означает:

базовые байты, составляющие объект, могут быть скопированы в массив из char или без знака char. Если содержимое массива char или unsigned char копируется обратно в объект, объект должен сохранить первоначальное значение.

Однако важно понимать, что указатели также являются тривиально копируемыми типами. Всякий раз, когда в структурах данных есть указатель, вы будете копировать, вы должны быть уверены, что их копирование будет правильным.

Примеры, где опасность может быть вызвана только тем, что объект может быть тривиально скопирован:

  • Реализация дерева, где ваши данные помещаются в смежный регион памяти, но с узлами, хранящими абсолютные адреса для дочерних узлов.
  • Создание нескольких экземпляров некоторых данных для повышения производительности многопоточности (для уменьшения сбоев кэша), с указателями владения внутри, указав где-нибудь
  • У вас есть плоский объект без указателей, но со встроенной сторонней структурой внутри. Третья структура в какой-то момент в будущем включает указатель, который не должен существовать два или более.

Поэтому всякий раз, когда вы делаете memcopying, имейте в виду, можно ли скопировать указатели в этом конкретном случае, и если все будет в порядке.

Поймите, что is_trivially_copyable - это только сильная проверка синтаксиса ", а не " семантический тест, на языке компилятора.

Ответ 4

Объекты с тривиальными конструкторами копирования , тривиальными операциями присваивания копий и тривиальные деструкторы могут быть скопированы с помощью memcpy или memmove

требования для специальной функции-члена класса T тривиальны:

Копировать конструкторы (cc) и операторы присваивания копий (ca)

  • Не предоставляется пользователем (это означает, что он неявно определен или дефолт), а если он по умолчанию, его подпись такая же, как неявно определенная
  • T имеет никаких виртуальных функций-членов
  • T имеет виртуальных базовых классов
  • Cc/ca, выбранный для каждой прямой базы T, тривиальный
  • Выбор cc/ca для каждого типа нестатического типа (или массива типа класса) из T тривиальный
  • T не имеет нестатических членов данных типа volatile-qualified (поскольку С++ 14)

деструкторы

  • Не предоставляется пользователем (это означает, что он неявно определен или дефолт)
  • Не является виртуальным (т.е. деструктор базового класса не является виртуальным)
  • Все прямые базовые классы имеют тривиальные деструкторы
  • Все нестатические члены данных типа класса (или массива типа класса) имеют тривиальные деструкторы

Просто объявление функции как = default не делает ее тривиальной (она будет тривиальной, если класс также поддерживает все остальные критерии для того, чтобы соответствующая функция была тривиальной) но явно записывает функцию в код пользователя, не позволяет ей быть тривиальным. Кроме того, все типы данных, совместимые с языком C (типы POD), можно копировать тривиально.

Источник: С++ Concurrency в действии и cppreference.com

Ответ 5

То, что я понял,

  • Объект должен иметь конструктор/деструктор по умолчанию.
  • Операции копирования по умолчанию и перемещения.
  • Нет статических и виртуальных функций с несколькими
  • Спецификаторы доступа для нестатических элементов данных предотвращают важные
  • Оптимизация макета имеет нестатический элемент или базу, которая не является стандартная компоновка.

вы можете проверить, если заданный тип - это pod (Обычные старые данные), используя стандартную функцию is_pod:: значение

Ссылка: язык программирования С++ 4-е издание