Каков порядок присваиваний внутри конструктора перемещения по умолчанию?

В настоящее время я работаю над собственным распределителем на С++. Этот распределитель должен регулярно дефрагментировать свою память, перемещая память и объекты. Эти сдвиги всегда нисходящие, а это означает, что адрес перемещаемого фрагмента памяти всегда уменьшается при его перемещении. Это не проблема, если старый блок памяти и новый блок памяти не перекрываются. Если они перекрываются, я сначала должен переместить объект во временную область за пределами памяти распределителя, а затем переместить его обратно в новый фрагмент памяти.

Если для перемещаемого типа std::is_tribuly_move_constructible имеет значение true, то я могу сохранить это дополнительное перемещение во временном фрагменте памяти, если порядок присваиваний внутри конструктора перемещения по умолчанию четко определен. Это приводит к моему вопросу: хорошо ли определен порядок назначений или он зависит от платформы?


person Brotcrunsher    schedule 01.07.2017    source источник
comment
Нельзя ли какой-либо такой объект перемещать вручную, например. по std::memmove?   -  person HeroicKatora    schedule 01.07.2017
comment
Какие задания вы имеете в виду?   -  person juanchopanza    schedule 01.07.2017
comment
Технически элементы данных создаются в том порядке, в котором они перечислены в определении класса. Который может совпадать или не совпадать с порядком, в котором они расположены в памяти; этот порядок гарантируется только между членами с одинаковым доступом. На практике тривиальный конструктор копирования/перемещения, скорее всего, выродится в вызов memcpy или аналогичный по правилу «как если». Тем не менее, компилятор теоретически может копировать спереди назад, или сзади вперед, или сначала нечетные байты, а затем четные байты; Я не думаю, что такие гипотетические реализации будут несоответствующими.   -  person Igor Tandetnik    schedule 01.07.2017
comment
Этот распределитель должен регулярно дефрагментировать свою память, перемещая память и объекты. Гм, на самом деле вы не можете этого сделать. Нет, если у вас нет полного знания о том, какие значения в этих объектах являются указателями, а какие нет. И к вашему сведению: указатели могут храниться в целочисленных значениях. Если вы перемещаете объект, не регулируя значение всего, что указывает на этот фрагмент памяти, вы что-то сломали.   -  person Nicol Bolas    schedule 01.07.2017
comment
Доказано, что сборка мусора с помощью memmove выполняется медленно. Вы можете быть на неправильном пути, будьте осторожны.   -  person rustyx    schedule 01.07.2017


Ответы (2)


Из стандарта (раздел 15.8.1 [class.copy.ctor])

(14) Неявно определенный конструктор копирования/перемещения для класса X, не являющегося объединением, выполняет почленное копирование/перемещение его баз и членов. [Примечание. Инициализаторы элементов по умолчанию для нестатических элементов данных игнорируются. См. также пример в 15.6.2. — конец примечания] Порядок инициализации такой же, как порядок инициализации баз и членов в определяемом пользователем конструкторе (см. 15.6.2)

Переход по ссылке приводит нас к Разделу 15.6.2 [class.base.init]

(13.3) Затем нестатические члены данных инициализируются в том порядке, в котором они были объявлены в определении класса (опять же, независимо от порядка meme-initializer s)


Не совсем отвечая на вопрос по существу, но, как также сказал в своем ответе Игорь Тандетник, законно преобразовать тривиальный конструктор в std::memmove

person HeroicKatora    schedule 01.07.2017

[basic.types]/3 Для любого тривиально копируемого типа T, если два указателя на T указывают на разные T объекты obj1 и obj2, где ни obj1, ни obj2 не являются подобъектами базового класса, если базовый байты (1.7), составляющие obj1, копируются в obj2, obj2 впоследствии будет содержать то же значение, что и obj1.

Таким образом, для тривиально копируемого типа было бы безопасно просто скопировать байты, например. с memmove. Вы можете проверить эту черту с помощью std::is_trivially_copyable.

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

[class]/6 Тривиально копируемый класс — это класс:

(6.1) - где каждый конструктор копирования, конструктор перемещения, оператор присваивания копирования и оператор присваивания перемещения (12.8, 13.5.3) либо удален, либо тривиален,

(6.2) - который имеет по крайней мере один неудаляемый конструктор копирования, конструктор перемещения, оператор присваивания копирования или оператор присваивания перемещения, и

(6.3) — который имеет тривиальный неудаляемый деструктор (12.4).

person Igor Tandetnik    schedule 01.07.2017
comment
Я упомянул об этом вместо неопределенного «все компиляторы поддерживают memmove». - person HeroicKatora; 01.07.2017