Ask писал(а):Это не так. К сожалению, с ключевым словом "const" в Паскале связан ряд заблуждений. На самом деле:
1) Ключевое слово "const" НЕ влияет непосредственно на способ передачи параметра -- параметр может быть передан как по ссылке,
так и по значению в зависимости от платформы, настроек оптимизации и т.д.
2) Чтобы гарантировать передачу по ссылке, следует использовать модификатор "constref", но он был реализован относительно недавно, и разработчики компилятора не рекомендуют его использовать без веской причины.
3) Ключевое слово "const" интерпретируется как обещание *от программиста компилятору*, что указанная переменная не поменяется *нигде в программе* в период выполнения функции/процедуры. Обратите внимание, что именно от программиста к компилятору, а не наоборот. Компилятор проверяет выполнение этого обещания только в простейших случаях. Если оно всё же будет нарушено, это может привести к очень трудно отлаживаемым ошибкам и падениям, особенно в случае refcounted типов, таких как строки и интерфейсы.
4) Разработчики языка принципиально не будут менять перечисленные выше пункты -- на этот счёт были долгие и бурные дискуссии, их позиция окончательна.
Таким образом, можно порекомендовать использовать префикс const осторожно, относиться к нему как к оптимизации,
и уж во всяком случае не расставлять бездумно где попало -- например, современные версии Lazarus больше не добавляют "const" автоматически к
параметру setter'а свойств объекта.
К модификаторам var и out перечисленные проблемы не относятся -- их можно свободно использовать там, где они нужны по смыслу
(не путая друг с другом, конечно).
Я бы сказал, что Ваше мнение довольно сомнительное по существу.
Во-первых, важно запомнить, что Вы пишите программу на языке высокого уровня не только и не сколько для компилятора, сколько для себя (для программиста). Компилятор - это машина, не для нее стараемся. Если программа не разовая, то программисту код читать еще 100 раз. И вот ради себя любимого, чтобы облегчить себе жизнь мы используем Const, префиксы, суфиксы и прочие вещи делающие код ясным и понятным.
Во-вторых, смысл Const не в ссылке, если нужна гарантированная ссылка, то пишем Var. Опитимизационный смысл Const в несоздании копии для строк и записей. Для числовых полей копия все же создается, т.к. трудоемкость передачи через стек ссылки и числа одинаковая, а внутри кода процедуры косвенная адрессация работает медленее. Так что в части оптимизации кода Const - это правильное решение.
Что касается нового "constref", то если честно, не понял зачем это сделали. Если ты используешь Const, то берешь на себя обязательство не менять поле. А если не менять поле, то зачем нужна гарантированная ссылка? Нужен указатель? Тогда используй Var или Pointer, будет яснее. Тут либо для совместимости с С, либо для запутывания логики, когда вроде бы Const, но можешь все же использовать не по назначению. Для обычного кода очевидно, что constref не нужно использовать, т.к. он скрывает ясность кода.
P.S. Не знаю точно, как делает FPC (для разных опций), но Дельфи при передаче строк как Proc(Const strPar:String), передает ссылку, и не делает копию строки. А Proc(strPar:String) должен сделать копию строки, т.к. меняя в процедуре strPar не должна изменяться строка в вызывающем коде.
Добавлено спустя 5 минут 21 секунду:Re: Inline vs CopyPast и способ передачи параметров в процедуры.iN0k писал(а):то есть шаманское изменение привело к интерисующему меня результату.
а шаманскому, по тому что для меня не очевидна.
может кто-нибудь разьяснить полученный результат?
Результат говорит о том, что inline - работает так, как требовалось. Он весь код вызываемой процедуры копирует в место вызова.
Что касается Вашего исходного вопроса:
- Код: Выделить всё
procedure F1(prm:rMyRecord);
begin
F0(@prm);
end;
То нужно сделать так:
- Код: Выделить всё
procedure F1(Var prm:rMyRecord);inline;
begin
F0(@prm);
end;
Тогда вызов F1 будет идентичен вызову F0 без дубляжа кода обработки из F0, но и без лишнего перевызова в F1.