Информация об изменениях

Сообщение Re[3]: Современные компиляторы и NRVO от 03.03.2024 11:41

Изменено 03.03.2024 12:55 rg45

Re[3]: Современные компиляторы и NRVO
Здравствуйте, _NN_, Вы писали:

_NN>Точно ли стандарт гарантирует использование конструктора перемещения прежде всего или всё же на усмотрение компилятора ?


По крайней мере, если полагаться на формулировки стандартов С++17 и C++20, то точно, (хотя они и несколько отличаются друг от друга):

https://timsong-cpp.github.io/cppwp/n4861/class.copy.elision#3

Здесь, конечно, здорово сбивает столку фраза "might be" в первом предложении абзаца:

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation might be used instead of a copy operation...


Но если прочитать абзац до конца, становится понятно, что это "might be" вовсе не является эквивалентом "на усмотрение компилятора", а относится к различным возможным исходам достаточно четко описанной процедуры, которую должен выполнить компилятор:

overload resolution to select the constructor for the copy or the return_­value overload to call is first performed as if the expression or operand were an rvalue. If the first overload resolution fails or was not performed, overload resolution is performed again, considering the expression or operand as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor or the return_­value overload to be called if elision is not performed, and the selected constructor or return_­value overload must be accessible even if the call is elided. — end note]


То есть, компилятор ДОЛЖЕН сперва попытаться обработать выражение под return как rvalue и только затем уже как lvalue. Тут нужно заметить, что если на первом шаге находится конструктор перемещения, который явно помечен как удаленный, то вторая попытка даже не выполняется.

В С++23 снова перетасовали все формулировки, снова нужно разбираться, чтоб понять, что именно изменилось. Но я не думаю, что этот принцип будет отменен.
Re[3]: Современные компиляторы и NRVO
Здравствуйте, _NN_, Вы писали:

_NN>Точно ли стандарт гарантирует использование конструктора перемещения прежде всего или всё же на усмотрение компилятора ?


По крайней мере, если полагаться на формулировки стандартов С++17 и C++20, то точно, (хотя они и несколько отличаются друг от друга):

https://timsong-cpp.github.io/cppwp/n4861/class.copy.elision#3

Здесь, конечно, здорово сбивает столку фраза "might be" в первом предложении абзаца:

An implicitly movable entity is a variable of automatic storage duration that is either a non-volatile object or an rvalue reference to a non-volatile object type. In the following copy-initialization contexts, a move operation might be used instead of a copy operation...


Но если прочитать абзац до конца, становится понятно, что это "might be" вовсе не является эквивалентом "на усмотрение компилятора", а относится к различным возможным исходам достаточно четко описанной процедуры, которую должен выполнить компилятор:

overload resolution to select the constructor for the copy or the return_­value overload to call is first performed as if the expression or operand were an rvalue. If the first overload resolution fails or was not performed, overload resolution is performed again, considering the expression or operand as an lvalue. [ Note: This two-stage overload resolution must be performed regardless of whether copy elision will occur. It determines the constructor or the return_­value overload to be called if elision is not performed, and the selected constructor or return_­value overload must be accessible even if the call is elided. — end note]


То есть, компилятор ДОЛЖЕН сперва попытаться обработать выражение под return как rvalue и только затем уже как lvalue. Тут нужно заметить, что если на первом шаге находится конструктор перемещения, который явно помечен как удаленный, то вторая попытка даже не выполняется.

В С++23 снова перетасовали все формулировки, снова нужно разбираться, чтоб понять, что именно изменилось. Но я не думаю, что этот принцип будет отменен.

P.S. Ну и такое еще, чисто обывательское соображение: это было бы совсем странно, если бы они требовали обязательной доступности семантики перемещения объекта в условиях, когда попытка использования этой самой семантики не является обязательной.