![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Функции и ее результат. [D7, XP]
maxon © (2008-07-07 23:07:00)I)
Например, есть такая функция:
function SomeFunc: TSomeType;
begin
// Как правильно писать
// Так:
Result:= value;
// или так:
SomeFunc:= value;
end;
Как же, все таки, правильно? Работают оба, но в чем разница?
II)
И еще, можно ли (правильно ли) использовать Result или ИМЯ_ФУНКЦИИ для работы внутри самой функции как с обычной переменной:
function SomeFunc: TSomeType;
begin
// Например
// Так:
Result:= Result * 2;
// или так:
SomeFunc:= SomeFunc * 2; // хотя, это уже рекурсия
end;
Для примера, вот функция, которая работает правильно (во всяком случаем результат верный):
function CharCount( const S: AnsiString; C: Char ): Cardinal;
var
i: Cardinal;
iLen: Cardinal;
begin
Result:= 0;
iLen:= Length( S );
if iLen < 1 then Exit;
for i:= 1 to iLen do
if S[i] = C then
Inc( Result );// <-- Разумно ли делать так или лучше создать отдельную переменную?
end;
Все это я спрашиваю еще и потому, что функции, для которых я это спрашиваю должны максимально быстро обрабатывать полученные данные, но при этом не использовать ЛИШНИХ переменных.
Amoeba (2008-07-09 10:53:00) [1]
> Германн © (09.07.08 01:48) [26]
>
>
> > Amoeba © (08.07.08 23:59) [25]
>
> Ой врёшь!
Не вру. И за базар отвечаю.
Anatoly Podgoretsky (2008-07-09 10:09:00) [2]Так и было - не было.
Выход TP6 послужил причиной для отказа от TASM
Германн (2008-07-09 01:48:00) [3]
> Amoeba © (08.07.08 23:59) [25]
Ой врёшь!
Amoeba (2008-07-08 23:59:00) [4]
> Ну это не совсем так. Во встроенном ассемблере можно было
> к этой переменной обратиться @Result.
В TP до TP6 встроенного ассемблера еще не было.
Игорь Шевченко (2008-07-08 22:00:00) [5]McSimm © (08.07.08 00:17) [8]
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
Создается компилятором
Германн (2008-07-08 21:58:00) [6]
> В старых версиях Паскаля не было псевдопеременной Result
Ну это не совсем так. Во встроенном ассемблере можно было к этой переменной обратиться @Result. Но по-моему только если возвращаемый результат имел тип String.
Буквоед. :)
Григорьев Антон (2008-07-08 08:39:00) [7]
> Result - это тоже самое, что если в старом паскале написать:
>
> Function NewInc(value:integer = 1):integer;
> var
> Result:integer;
> begin
> Result:=Result+value;
> NewInc:=Result;
> end;
Result - это не совсем локальная переменная, это, скорее, неявный выходной параметр. Для типов с автоматической инициализацией и финализацией можно почувствовать разницу: http://www.rsdn.ru/article/Delphi/dynarrays.xml#ESHAC
> Как же, все таки, правильно? Работают оба, но в чем разница?
В старых версиях Паскаля не было псевдопеременной Result, там надо было присваивать значение через имя функции. В Delphi появился более удобный механизм присваивания через Result, но старый способ оставлен для совместимости с существующим кодом.
Германн (2008-07-08 02:12:00) [8]
> @!!ex © (08.07.08 01:44) [16]
>
> > [15] Германн © (08.07.08 01:34)
> > незрелых. :)
>
> Вызов функции как процедуры - это общепринятая практика.
>
> Например, лично я использую часто эту возможность, когда
> нужно при чтении из файла какой-то блок проигнорировать.
>
>
Надеюсь, ты в отличие от РА находишься в трезвой памяти.
То что ты, как и многие другие, часто используешь вызов функции как процедуры - это нормально. Но ты не "незрелый".
@!!ex (2008-07-08 01:51:00) [9]
Function Test(const a,b,c,d,e,f,g,h,i,j,k:TVector):TVector;
begin
Result:=Test2(a,b,c,d,e,f,g,h,i,j,k);
end;
int __stdcall sub_403848(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
{
return sub_40382C(a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
Посыпаю голову пеплом...
@!!ex (2008-07-08 01:48:00) [10]Хотя, конечно, пример не показательный, т.к. все в регистрах помещается.
@!!ex (2008-07-08 01:47:00) [11]Pascal:
Function Normal(const a,b:TVector):TVector;
begin
Result:=Normalize(CrossVectors(a,b));
end;
Assembler(IDA Pro 5.2)
.text:00403904 sub_403904 proc near ; CODE XREF: .itext:004040EF\x19p
.text:00403904 push ebx
.text:00403905 push esi
.text:00403906 push edi
.text:00403907 add esp, 0FFFFFFF4h
.text:0040390A mov edi, ecx
.text:0040390C mov esi, edx
.text:0040390E mov ebx, eax
.text:00403910 mov ecx, esp
.text:00403912 mov edx, esi
.text:00403914 mov eax, ebx
.text:00403916 call sub_4038A4
.text:0040391B mov eax, esp
.text:0040391D mov edx, edi
.text:0040391F call sub_4038D8
.text:00403924 add esp, 0Ch
.text:00403927 pop edi
.text:00403928 pop esi
.text:00403929 pop ebx
.text:0040392A retn
.text:0040392A sub_403904 endp
C(HexRays 1.0)
int __cdecl sub_403904()
{
sub_4038A4();
return sub_4038D8();
}
Как видно, ни о какой переменной Result речи не идет.
Даже больше: параметры насквозь проходят.
@!!ex (2008-07-08 01:44:00) [12]Кстати, я не прав. Зря клевещу на Борланда. Все отлично сделано.
@!!ex (2008-07-08 01:44:00) [13]> [15] Германн © (08.07.08 01:34)
> незрелых. :)
Вызов функции как процедуры - это общепринятая практика.
Например, лично я использую часто эту возможность, когда нужно при чтении из файла какой-то блок проигнорировать.
Речь не о том, что Result - это совсем плохое решение.
Речь о том, что бывают случаи, когда лишняя переменная ненужна. И такие случаи часто встречаются.
Я почему об этом заговорил?
Когда пишешь много вычислений в реалтайме, когда функции постоянно друг друга вызывают, выделение памяти на лишнюю процедуру - может очень даже заметно снизить скорость. Особенно если сама функция - три строчки на ассемблере. Приходится переписывать все на асме... там то переменные не выделяются.
Германн (2008-07-08 01:34:00) [14]
> @!!ex ©
> > [12] Германн © (08.07.08 00:45)
>
> Не факт.
> Ведь я результат той же функции Normal могу передать в другую
> функцию.
>
Не факт. Не спорю. Но сей вариант не вписывается в ситуацию
> ИМХО далеко не лучшая идея со стороны борланда, т.к. в ряде
> случаев лишняя переменная не нужна.
> к тому же бывают случаи, когда результат выполнения функции
> игнорируется. Не часто, но бывает.
>
Бывают. Но в таких случаях часто стоит пересмотреть логику работы и либо заменить функцию процедурой, либо разделить код функции на две части. Я не против решения Борланда разрешить вызов функции как процедуры, но понимаю как это плохо для некоторых незрелых. :)
@!!ex (2008-07-08 00:55:00) [15]к тому же бывают случаи, когда результат выполнения функции игнорируется. Не часто, но бывает.
А с out - не проигнорируешь.
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
Если это действительно так, то я не прав.
@!!ex (2008-07-08 00:53:00) [16]> Function Normal(var a,b:vector):vector;
Это сути не меняет, если вектор - это массив байтов на 4 элемента, то тоже самое.
> [12] Германн © (08.07.08 00:45)
Не факт.
Ведь я результат той же функции Normal могу передать в другую функцию.
В случае использвания функции я сделаю просто:
SomeFunction(Normal(a,b));
А если процедура с результатом в параметрах, придется опять же заводить лишнюю переменную.
c:vector;
Normal(a,b,c);
SomeFunction(c);
Германн (2008-07-08 00:45:00) [17]
> @!!ex © (08.07.08 00:21) [10]
>
> > [5] Ega23 © (08.07.08 00:08)
>
> использование out или var перенесет переменную на сторону
> вызывающего и все.
>
Дык на стороне вызывающего и так уже создана переменная, которой присваивается результат функции. Не так ли?
Ega23 (2008-07-08 00:27:00) [18]
> Здесь создается 3! переменных типа vector.
3! - это "три" или шесть (три факториал)?
А если так
Function Normal( vara,b:vector):vector;
@!!ex (2008-07-08 00:21:00) [19]> [5] Ega23 © (08.07.08 00:08)
использование out или var перенесет переменную на сторону вызывающего и все.
Например расчет нормали:
Function Normal(a,b:vector):vector;
begin
Result:=Normalize(CrossVectors(a,b));
end;
Здесь создается 3! переменных типа vector.
Хотя достаточно одного создания при перемножении векторов.
> [7] umbra © (08.07.08 00:17)
ночь уже... там еще одной переменной не хватает, к ней как раз value и надо прибавлять.
maxon (2008-07-08 00:20:00) [20]
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
А вот, стоит! Интересно все таки.