C ++ представление значений нетривиально копируемых типов - PullRequest
4 голосов
/ 18 марта 2019

Текущий черновик стандарта C ++ (март 2019 г.) имеет следующий абзац ([basic.types] p.4) (выделено мной):

Представление объекта объекта типаT - это последовательность из N беззнаковых объектов char, занятых объектом типа T, где N равно sizeof (T).Представление значения объекта типа T - это набор битов, которые участвуют в представлении значения типа T. Биты в представлении объекта, которые не являются частью представления значения, являются битами заполнения. Для тривиально копируемых типов представление значения - это набор битов в представлении объекта, который определяет значение, которое является одним дискретным элементом набора значений, определенного реализацией .

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

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

class some_other_type
{
    int a;
    std::string s;
};

пользователь решает, что значение объекта типа some_other_type включает символы, принадлежащие строке s.

Я пытался придумать примеры, в которых тот факт, что некоторые биты объекта (которые не легко копируются ) представление значения находятся за пределами его представление объекта является неявным (реализация должна делать это, пользователь не решает это произвольно).

Один из примеров, который я привел, заключается в том, что представление значения базыподобъект класса с виртуальными методами может включать биты из представления объекта всего объекта, которому он принадлежит, поскольку подобъект базового класса может вести себя по-разному (может «иметь другое значение») по сравнению с ситуацией, в которойэто был бы сам объект целиком.

Еще один пример, который, как я думаю, это тот факт, что vtable также может бытьr * значения объекта, чей указатель vtable указывает на него.

Верны ли эти примеры?Есть ли другие примеры?

Было ли выделенное предложение введено стандартным комитетом из-за того, что семантическое «значение» объекта может быть решено пользователем (как в двух связанных ответах), или потому чтоо том, что реализации могут решить (или могут быть вынуждены) сделать это, или оба?

Спасибо.

1 Ответ

6 голосов
/ 18 марта 2019

В моей интерпретации основное внимание выделенного вами предложения составляет эта часть:

Для тривиально копируемых типов представление значения представляет собой набор битов в представлении объекта это определяет значение, которое является одним отдельным элементом набора значений, определенных реализацией.

По существу, [basic.types] # 4 стандарта говорит, что "каждый объект имеет набор битов O, которые являются его объектным представлением, и набор битов, которые являются его представлением значения V. Набор P = O without V является битами заполнения. Для тривиально копируемых типов V является подмножеством O».Последнее важно, потому что это означает, что копирование вокруг набора O битов также безопасно копирует вокруг V для тривиально копируемых типов, таким образом, значение сохраняется.То, как вы определяете V для других типов, здесь не имеет значения (установите его для всей абстрактной машины, если хотите).


Чтобы ответить на пересмотренный вопрос, заданный в комментариях:

почему реализация не может сказать, что означает 1110000100010001111, если это было объектное представление нетривиально копируемого объекта?Это потому, что есть некоторые другие биты (за пределами этого представления объекта), которые помогают определить, какое значение имеет объект?

Давайте возьмем std::string в качестве примера.Это не просто копирование, потому что оно имеет дело с управлением памятью.

Если бы два std::string объекта имели одинаковый битовый шаблон, они означали бы одно и то же?

Нет.Существует , по крайней мере, одна реализация , которая указывает на оптимизацию небольшой строки, имея указатель буфера на себя (gcc).После уничтожения буфер освобождается, если (и только если) он не указывает на это точное местоположение.

Очевидно, что два std::string объекта, находящихся в разных местах, должны (в этой реализации) представлять одно и то же(маленькое) строковое значение с различными битовыми комбинациями (указатели буфера должны быть разными).И что более важно, одна и та же битовая комбинация в двух объектах может означать очень разные вещи - она ​​может указывать SSO в одном случае, но не в другом.

Как вы можете видеть, в представлении значения участвует дополнительная информациякаждый std::string здесь: его местоположение в памяти (то есть значение this).Как именно это представляется в битах, в стандарте далее не указывается.

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