Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Функции и ее результат. [D7, XP]


Страницы:   1 2

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 не используется,
>  она и не создается.

А вот, стоит! Интересно все таки.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо