Побайтные копии типов в C ++ 11? - PullRequest
5 голосов
/ 24 сентября 2011

Стандарт C ++ 11 гарантирует, что побайтовые копии всегда действительны для типов POD. Но как насчет некоторых тривиальных типов?

Вот пример:

struct trivial
{
  int x;
  int y;
  trivial(int i) : x(2 * i) { std::cout << "Constructed." << std::endl; }
};

Если бы я копировал эту структуру, побайтно, гарантированно ли она будет копироваться, даже если технически это не POD? Когда рисуется линия, когда не нормально, чтобы копировать объект с помощью байтов?

Ответы [ 3 ]

9 голосов
/ 24 сентября 2011

Да, это гарантированно правильно скопировано.

Цитирование FDIS, §3.9 / 2:

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

И §3,9 / 3:

Для любого тривиально копируемого типа T, если два указателя на T указывают на различные T объекты obj1 и obj2, где ни obj1, ни obj2 не являются подобъект базового класса, если нижележащие байты, составляющие obj1, копируются в obj2, obj2 должны впоследствии содержать то же значение, что и obj1.

Итак, требования, о которых вы спрашиваете, §3.9 / 9:

Арифметические типы, типы перечисления, типы указателей, указатели на типы элементов, std::nullptr_t и cv-квалифицированные версии этих типов вместе называются скалярными типами . Скалярные типы, POD-классы, массивы таких типов и cv-квалифицированные версии этих типов вместе называются POD-типы . Скалярные типы, тривиально копируемые типы классов, массивы таких типов и cv-квалифицированные версии этих типов вместе называются тривиально копируемыми типами .

И §9 / 6:

A тривиально копируемый класс - это класс, который:

  • не имеет нетривиальных конструкторов копирования,
  • не имеет нетривиальных конструкторов перемещения,
  • не имеет нетривиальных операторов назначения копирования,
  • не имеет нетривиальных операторов назначения перемещения, а
  • имеет тривиальный деструктор.
5 голосов
/ 24 сентября 2011

C ++ 11 разбил определение типов POD на более полезные категории, в частности, «тривиальный» и «стандартный макет». Ваш пример - стандартный макет, который можно копировать тривиально, хотя конструктор не позволяет ему быть полностью тривиальным. Тривиально копируемые типы гарантированно безопасны для побайтного копирования:

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

Таким образом, нет, безопасное копирование состояния POD таким образом не требуется, но можно определить подмножество типов, не относящихся к POD, которые могут быть.

3 голосов
/ 24 сентября 2011

Если стандарт гласит, что он определен только для типов POD (я еще не изучал стандарт C ++ 11 подробно, поэтому я не знаю, является ли ваше утверждение правильным или нет (a) ) и вы делаете это для не POD типа, это не определенное поведение.Период.

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


(a) После дополнительного расследования кажется, что ваш конкретный случай в порядке.Раздел 3.9 / 3 стандарта ( n3242 черновик , но я бы удивился, если бы он сильно изменился по сравнению с этим поздним черновиком) гласит:

Для любого тривиально копируемого типа T, если два указателя на T указывают на разные объекты T obj1 и obj2, где ни obj1, ни obj2 не являются подобъектом базового класса, если нижележащие байты, составляющие obj1, копируются в obj2, впоследствии obj2 будет иметь то же значение, что и obj1.

Раздел 9 определяет (на высоком уровне), что означает «тривиально копируемое»:

Тривиально копируемый класс - это класс, который:
- не имеет нетривиальныхконструкторы копирования (12.8),
- нет нетривиальных конструкторов перемещения (12.8),
- нет нетривиальных операторов присваивания копии (13.5.3, 12.8),
- нет нетривиальных операторовоператоры присваивания перемещений (13.5.3, 12.8) и
- имеют тривиальный деструктор (12.4).

с указанными разделами, более подробно описывающими каждую область, 12.8 для копирования и перемещения объектов класса и 13.5.3 для заданий.

...