2016-06-26 8 views
15

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html«Гарантированное копирование» (P0135, C++ 1z) может потребовать поломки ABI?

Вышеизложенное предложение «Гарантированный Copy Пропуска» был признан в C++ рабочего документа в заседании июня 2016 года в Оулу, Финляндия, который затем проголосовали за публикации в качестве проекта комитета. Надеюсь, это приведет к публикации в качестве стандарта C++ 17 в следующем году.

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

Мой вопрос: «Могло ли это новое требование нарушить совместимость с ABI для компиляторов, которые ранее не могли бы выполнить копирование в этих обстоятельствах или внедрили его таким образом, который не будет совместим с новыми требованиями?»

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

+4

Я могу представить себе ABI (если это смешно), который будет нарушен этим изменением. Достаточно ли этого, или вы ищете фактические экземпляры ABI, которые фактически используются фактическим компилятором, не являющимся игрушкой, который ломается? – Yakk

+4

Как вы можете сломать то, чего не существует? – user3104201

+0

"* Я думаю о таких вещах, как инициализации, которые позволяют копировать, когда создание объекта может быть встроено, но не при пересечении границ единицы компиляции. *« Я не знаю таких обстоятельств, когда это было бы возможно. –

ответ

11

Когда функция вызывается, функция должна вернуть значение. Это значение требует памяти, чтобы жить, но возвращаемое значение должно выжить вне самой функции. ABI определяет, как все это работает. Вообще говоря, это происходит от вызывающего, предоставляющего кусочек памяти размера/выравнивания для возвращаемого значения функции.

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

Негарантированное копирование означает, что ни одна из этих копий не требуется. На стороне возвращающей функции компилятору разрешено просто использовать память возвращаемого значения внутри, генерируя это значение, поэтому оператору return ничего не нужно копировать. И на принимающей стороне, если память будет использоваться для инициализации объекта стека, тогда ее не нужно копировать в эту память.

Гарантированное копирование означает, что если принимающая сторона инициализирует объект того же типа, то приемник не будет учитывать, имеет ли объект конструктор копирования/перемещения. Таким образом, код, вызывающий такую ​​функцию, как auto t = Func();, не будет рассматривать его как возможную операцию копирования в t. Обработка компилятором этого кода вызовет Func с памятью возвращаемого значения, которая находится в пространстве стека для t.

И на стороне вызываемого лица, если вы сразу возвращаете prvalue, тогда нет необходимости в создании конструктора copy/move. Вызов будет строить prvalue непосредственно в памяти возвращаемого значения.

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

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

ABI определяет интерфейс; то, что вы делаете с этим интерфейсом, зависит от вас.

В качестве примера рассмотрим Itanium ABI on return values. Он позволяет хранить типы классов в регистре, но только, если у них есть тривиальные конструкторы копирования/перемещения. В противном случае, независимо от их содержимого, они должны быть сконструированы в памяти, предоставляемой вызывающей функцией. Если класс тривиально можно копировать, то вы не можете определить разницу между elision и non-elision.

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

Может ли такой ABI существовать? У меня нет особых знаний, чтобы сказать, что это невозможно. Имеет ли это? Я скорее сомневаюсь в этом, так как такой ABI сделает вообще довольно сложно.

+0

Вопрос тогда сводится к тому, существуют ли какие-либо существующие компиляторы, которые реализуют память возвращаемого значения каким-то глупым способом, который будет вибрировать либо с вызывающей записью результата непосредственно в него, либо с вызывающим, используя результат непосредственно из него. – Novelocrat

+0

@Novelocrat: ABI определяет, как значения передаются механически через вызовы функций. Единственный способ, которым это может быть испорчено, - это если компилятор не следовал за ABI. Это гораздо более серьезная проблема, чем неправильная реализация гарантированного elision. –

+3

@Nicol: что, если вместо того, чтобы позволить вызывающему указать произвольное местоположение, в котором будет помещено возвращаемое значение, ABI указывает его относительно чего-то другого (расположение параметров, адрес возврата и т. Д.). Тогда вызывающему абоненту не удастся избежать последующей передачи из определенного ABI местоположения (которое может быть перезаписано дополнительными вызовами функций до окончания срока действия объекта) в более долговечное местоположение. –

 Смежные вопросы

  • Нет связанных вопросов^_^