Форум: "Начинающим";
Текущий архив: 2008.08.10;
Скачать: [xml.tar.bz2];
ВнизФункции и ее результат. Найти похожие ветки
← →
maxon (2008-07-07 23:07) [0]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;
Все это я спрашиваю еще и потому, что функции, для которых я это спрашиваю должны максимально быстро обрабатывать полученные данные, но при этом не использовать ЛИШНИХ переменных.
← →
McSimm © (2008-07-07 23:11) [1]
> Inc( Result ); // <-- Разумно ли делать так или лучше создать
> отдельную переменную?
Разумно. Это и есть отдельная переменная, специально для этих целей.
← →
maxon (2008-07-07 23:33) [2]Нашел следующий ответ:
Переменная Result используется, чтобы хранить значение результата, возвращенное функцией.
Когда функция начинается, Delphi сам автоматически создает эту переменную. Она имеет тот же самый тип, как и возвращаемый тип функции. Результат может использоваться в функции повсюду, как будто она была явно объявлена.
И еще, как дальше объясняется писать Result вместо ИмяФункции это новый механизм возвращения значения.
← →
@!!ex © (2008-07-07 23:41) [3]> SomeFunc:= SomeFunc * 2; // хотя, это уже рекурсия
Так нельзя, потому что берется не значение, а вызывается опять функция.
> Result:= value;
Так можно. Result - это тоже самое, что если в старом паскале написать:
Function NewInc(value:integer = 1):integer;
var
Result:integer;
begin
Result:=Result+value;
NewInc:=Result;
end;
ИМХО далеко не лучшая идея со стороны борланда, т.к. в ряде случаев лишняя переменная не нужна. А ручками создать переменную Result - не проблема. Я сейчас так на сях делаю:cVector4f cVector4f::operator* (const cMatrix4x4 &M)
{
cVector4f Result;
Result.x = x*M._11+y*M._21+z*M._31+M._41;
Result.y = x*M._12+y*M._22+z*M._32+M._42;
Result.z = x*M._13+y*M._23+z*M._33+M._43;
Result.w = x*M._14+y*M._24+z*M._34+M._44;
return Result;
};
← →
maxon (2008-07-08 00:01) [4]Думаю ответ исчерпывающий, Спасибо всем!!!
← →
Ega23 © (2008-07-08 00:08) [5]
> ИМХО далеко не лучшая идея со стороны борланда, т.к. в ряде
> случаев лишняя переменная не нужна.
В этом ряде случаев можно воспользоваться var-параметром, ы?
← →
Германн © (2008-07-08 00:12) [6]
> Ega23 © (08.07.08 00:08) [5]
Тогда уж уместнее воспользоваться out-параметром.
← →
umbra © (2008-07-08 00:17) [7]
> Function NewInc(value:integer = 1):integer;
> var
> Result:integer;
> begin
> Result:=Result+value;
> NewInc:=Result;
> end;
Ничего, что локальные переменные не инициализируюются?
← →
McSimm © (2008-07-08 00:17) [8]тогда процедурой нельзя будет пользоваться как функцией.
> в ряде случаев лишняя переменная не нужна.
не проверял, но уверен, что когда Result не используется, она и не создается.
← →
maxon (2008-07-08 00:20) [9]
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
А вот, стоит! Интересно все таки.
← →
@!!ex © (2008-07-08 00:21) [10]> [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 и надо прибавлять.
← →
Ega23 © (2008-07-08 00:27) [11]
> Здесь создается 3! переменных типа vector.
3! - это "три" или шесть (три факториал)?
А если такFunction Normal(var a,b:vector):vector;
← →
Германн © (2008-07-08 00:45) [12]
> @!!ex © (08.07.08 00:21) [10]
>
> > [5] Ega23 © (08.07.08 00:08)
>
> использование out или var перенесет переменную на сторону
> вызывающего и все.
>
Дык на стороне вызывающего и так уже создана переменная, которой присваивается результат функции. Не так ли?
← →
@!!ex © (2008-07-08 00:53) [13]> 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);
← →
@!!ex © (2008-07-08 00:55) [14]к тому же бывают случаи, когда результат выполнения функции игнорируется. Не часто, но бывает.
А с out - не проигнорируешь.
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
Если это действительно так, то я не прав.
← →
Германн © (2008-07-08 01:34) [15]
> @!!ex ©
> > [12] Германн © (08.07.08 00:45)
>
> Не факт.
> Ведь я результат той же функции Normal могу передать в другую
> функцию.
>
Не факт. Не спорю. Но сей вариант не вписывается в ситуацию
> ИМХО далеко не лучшая идея со стороны борланда, т.к. в ряде
> случаев лишняя переменная не нужна.
> к тому же бывают случаи, когда результат выполнения функции
> игнорируется. Не часто, но бывает.
>
Бывают. Но в таких случаях часто стоит пересмотреть логику работы и либо заменить функцию процедурой, либо разделить код функции на две части. Я не против решения Борланда разрешить вызов функции как процедуры, но понимаю как это плохо для некоторых незрелых. :)
← →
@!!ex © (2008-07-08 01:44) [16]> [15] Германн © (08.07.08 01:34)
> незрелых. :)
Вызов функции как процедуры - это общепринятая практика.
Например, лично я использую часто эту возможность, когда нужно при чтении из файла какой-то блок проигнорировать.
Речь не о том, что Result - это совсем плохое решение.
Речь о том, что бывают случаи, когда лишняя переменная ненужна. И такие случаи часто встречаются.
Я почему об этом заговорил?
Когда пишешь много вычислений в реалтайме, когда функции постоянно друг друга вызывают, выделение памяти на лишнюю процедуру - может очень даже заметно снизить скорость. Особенно если сама функция - три строчки на ассемблере. Приходится переписывать все на асме... там то переменные не выделяются.
← →
@!!ex © (2008-07-08 01:44) [17]Кстати, я не прав. Зря клевещу на Борланда. Все отлично сделано.
← →
@!!ex © (2008-07-08 01:47) [18]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:004040EFp
.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:48) [19]Хотя, конечно, пример не показательный, т.к. все в регистрах помещается.
← →
@!!ex © (2008-07-08 01:51) [20]
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);
}
Посыпаю голову пеплом...
← →
Германн © (2008-07-08 02:12) [21]
> @!!ex © (08.07.08 01:44) [16]
>
> > [15] Германн © (08.07.08 01:34)
> > незрелых. :)
>
> Вызов функции как процедуры - это общепринятая практика.
>
> Например, лично я использую часто эту возможность, когда
> нужно при чтении из файла какой-то блок проигнорировать.
>
>
Надеюсь, ты в отличие от РА находишься в трезвой памяти.
То что ты, как и многие другие, часто используешь вызов функции как процедуры - это нормально. Но ты не "незрелый".
← →
Григорьев Антон © (2008-07-08 08:39) [22]
> 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 21:58) [23]
> В старых версиях Паскаля не было псевдопеременной Result
Ну это не совсем так. Во встроенном ассемблере можно было к этой переменной обратиться @Result. Но по-моему только если возвращаемый результат имел тип String.
Буквоед. :)
← →
Игорь Шевченко © (2008-07-08 22:00) [24]McSimm © (08.07.08 00:17) [8]
> не проверял, но уверен, что когда Result не используется,
> она и не создается.
Создается компилятором
← →
Amoeba © (2008-07-08 23:59) [25]
> Ну это не совсем так. Во встроенном ассемблере можно было
> к этой переменной обратиться @Result.
В TP до TP6 встроенного ассемблера еще не было.
← →
Германн © (2008-07-09 01:48) [26]
> Amoeba © (08.07.08 23:59) [25]
Ой врёшь!
← →
Anatoly Podgoretsky © (2008-07-09 10:09) [27]Так и было - не было.
Выход TP6 послужил причиной для отказа от TASM
← →
Amoeba © (2008-07-09 10:53) [28]
> Германн © (09.07.08 01:48) [26]
>
>
> > Amoeba © (08.07.08 23:59) [25]
>
> Ой врёшь!
Не вру. И за базар отвечаю.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2008.08.10;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.007 c