Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.03.30;
Скачать: CL | DM;

Вниз

const в параметрах   Найти похожие ветки 

 
махс   (2008-03-02 11:23) [0]

Загадка для меня. В каких случаях в процедуру или функцию передают значение константой;

Я понимаю, что это означает. Но вот когда именно это применяют не пойму. Бывает выжу чужой исходник, в функцию передают пять параметров - не один внутри функции не изменяют, а с констнтой идет только самый первый.

Поясните?

Спасибо.


 
Anatoly Podgoretsky ©   (2008-03-02 11:30) [1]

> махс  (02.03.2008 11:23:00)  [0]

А пример?


 
махс   (2008-03-02 13:08) [2]

Ну вот пример из боландовских исходников:

function StrToIntDef(const S: string; Default: Integer): Integer;
var
 E: Integer;
begin
 Val(S, Result, E);
 if E <> 0 then Result := Default;
end;


Почему бы тут не передать Default, как const?


 
{RASkov} ©   (2008-03-02 13:23) [3]

> Почему бы тут не передать Default, как const?

Ну "забыли" борландовцы....

> Загадка для меня. В каких случаях в процедуру или функцию
> передают значение константой;

Тыж говоришь:

> Я понимаю, что это означает.

Откуда тогда такие вопросы?
Значит ты не понимаешь :(

В данном случае не смотри на чужой код с поспешными выводами, а разберись досканально - что и для чего...


 
Игорь Шевченко ©   (2008-03-02 13:33) [4]


>
> Почему бы тут не передать Default, как const?


Потому что для Integer без разницы, как его передавать, а для string разница есть. А раз без разницы, зачем лишние буквы набивать.


 
Anatoly Podgoretsky ©   (2008-03-02 13:34) [5]


> Бывает выжу чужой исходник, в функцию передают пять параметров

Где пять параметров.
А в приведеном коде без разницы, что const, что без.
Приводи примет, а то беспредметный разговор.


 
{RASkov} ©   (2008-03-02 14:20) [6]

> Потому что для Integer без разницы, как его передавать

Что-то я в замешательстве....

procedure M(const I: Integer);
и
procedure M1(I: Integer);
одинаковые что ли?
т.е. вызов М1 не "раздвоит" значение?? Что-то здесь не так..... а ведь "раздвоит", так как:
N:=5;
M1(N);
ShowMessage(IntTostr(N));

при:
procedure M1(I: Integer);
begin
 ....
 I:=Random(I);
end;

Покажет(должно показать) - 5...

или я не верно понял [4],[5] :( ...т.е. не в контексте вопроса автора, а в целом.
Я так считал, что:
1 - function StrToIntDef(const S: string; Default: Integer): Integer;
2 - function StrToIntDef(const S: string; const Default: Integer): Integer;
вторая функция будет работать "быстрее" первой.... ибо не будет копироваться значение, а передастся ссылка....


 
Anatoly Podgoretsky ©   (2008-03-02 14:28) [7]

> {RASkov}  (02.03.2008 14:20:06)  [6]

Ссылки для интегер работают медленнее значений.


 
{RASkov} ©   (2008-03-02 14:29) [8]

Почему появилось [6].
Я пробегся по нескольким местам в VCL и нигде не встретил (const xx: Integer) или (const xx: Cardinal).....
Var - были, а конст нигде.... только по значению..... Странно все это :)
В прочем я не так и много мест просмотрел....


 
{RASkov} ©   (2008-03-02 14:30) [9]

> [7] Anatoly Podgoretsky ©   (02.03.08 14:28)

Ясно.... спасибо)


 
Игорь Шевченко ©   (2008-03-02 14:35) [10]


> procedure M(const I: Integer);
> и
> procedure M1(I: Integer);
> одинаковые что ли?


С точки зрения передачи параметров, быстродействия и прочих аспектов времени выполнения абсолютно одинаковые.
С точки зрения компиляции компилятор будет ругаться, если внутри процедуры параметру будет что-то присваиваться.

Давно бы откомпилировал и посмотрел


 
{RASkov} ©   (2008-03-02 14:49) [11]

> [10] Игорь Шевченко ©   (02.03.08 14:35)
> Давно бы откомпилировал и посмотрел

Мне известно что будет с "const" и без нее...
Я именно про саму передачу параметра.... с const(var) - у нас одна "переменная", без - две. (утрировано)

> С точки зрения передачи параметров, быстродействия и прочих
> аспектов времени выполнения абсолютно одинаковые.

Что-то опять не то.... См [7] :(

> С точки зрения компиляции компилятор....

Ну его точка зрения мне понятна...:)


 
Anatoly Podgoretsky ©   (2008-03-02 14:53) [12]


> Что-то опять не то.... См [7] :(

Не путай передачу по значению, с передачей по ссылке.
И смотри окно CPU что бы определить как передается интегер при const, var и без модификатора.


 
Игорь Шевченко ©   (2008-03-02 15:12) [13]

{RASkov} ©   (02.03.08 14:49) [11]


> > С точки зрения передачи параметров, быстродействия и прочих
>
> > аспектов времени выполнения абсолютно одинаковые.
>
> Что-то опять не то.... См [7] :(


А что смотреть на 7 ? Лучше смотреть на грамматику языка. В которой сказано, что параметры передаются по значению, если не указано слово var.


 
{RASkov} ©   (2008-03-02 15:50) [14]

> [12] Anatoly Podgoretsky ©   (02.03.08 14:53)
> Не путай передачу по значению, с передачей по ссылке.

А где я что напутал?

> И смотри окно CPU

А вот туда я не умею смотреть, т.е. смотреть-то туда умею, но там ничего не понимаю :(


> [13] Игорь Шевченко ©   (02.03.08 15:12)
> В которой сказано, что параметры передаются по значению,
> если не указано слово var

или const... еще out ...

>
Ладно.... фик с ними :) Что-то мы тут запутались..... т.е. я запутался и вас путаю... )


 
oxffff ©   (2008-03-02 16:10) [15]


> махс   (02.03.08 13:08) [2]
> Ну вот пример из боландовских исходников:
>
> function StrToIntDef(const S: string; Default: Integer):
>  Integer;


В данном случае при const имеет смысл для S, по скольку S является  managed типом (не в терминах .NET естествено), const означает, что локальная переменая является синонимом
(это подавляет вызовы addref/release при assign op, и finalize при scope exit )

переданного параметра с ораниченным временем жизни

Однако оные выкрутасы могут приводить к проблемам, например вот одна из них выдуманная на ходу

var GlobalA:string;

implementation

{$R *.dfm}

procedure HarmfulProc(const a:string);
var b:string;
begin
GlobalA:=""; //Освобождает память
b:=a;         //Копируем invalid ref            //
end;          //Освобождает память снова //AV

procedure TForm1.Button1Click(Sender: TObject);
begin
GlobalA:="SomeText";
GlobalA:=GlobalA+GlobalA;
HarmfulProc(GlobalA);
end;


 
oxffff ©   (2008-03-02 16:12) [16]


> (это подавляет вызовы addref/release при assign op, и finalize
> при scope exit )


Подавляет вызов  addref при передачи параметра.


 
{RASkov} ©   (2008-03-02 16:19) [17]

> [15] oxffff ©   (02.03.08 16:10)
> Однако оные выкрутасы могут приводить к проблемам, например
> вот одна из них выдуманная на ходу

Помоему это нужно специально так придумать, да и не каждому дано так придумать :) я про код)


 
oxffff ©   (2008-03-02 16:24) [18]


> {RASkov} ©   (02.03.08 16:19) [17]


Пример надуман, однако такая ситуация имеет место быть.
Такая ситуация может неявно возникнуть в многопоточном приложении.


 
Loginov Dmitry ©   (2008-03-02 19:05) [19]

> Почему бы тут не передать Default, как const?


1) это ничего не даст. Просто нельзя будет изменять значение переменной в процедуре, вот и все.
2) const и var при передаче глобальных переменных является потенциальной проблемой в многопоточном приложении.

А переменные String передавать с Const - это скорее правило хорошего тона. Именно в примере [2] оптимизации от этого никакой нет, т.к. нет обращения к отдельным символам строки. В других же случаях наличие Const может заметно улучшить производительность приложения по сравнению с его отсутствием.


 
oxffff ©   (2008-03-02 19:30) [20]


> Loginov Dmitry ©   (02.03.08 19:05) [19]


Разница есть.

procedure abc(s:string);
begin

end;

procedure abcEx(const s:string);
begin

end;

procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
   Tick1,Tick2:DWORD;
begin
Tick1:=GetTickCount;
for i:=0 to 100000000 do abc("123");
Tick1:=GetTickCount-Tick1;

Tick2:=GetTickCount;
for i:=0 to 100000000 do abcEx("123");
Tick2:=GetTickCount-Tick2;

showmessage(inttostr(Tick1)+" "+inttostr(Tick2));
end;


 
oxffff ©   (2008-03-02 19:39) [21]


> Loginov Dmitry ©   (02.03.08 19:05) [19]
> > Почему бы тут не передать Default, как const?
>
>
> 1) это ничего не даст. Просто нельзя будет изменять значение
> переменной в процедуре, вот и все.


Опять заблуждение, хочешь пример?

TypeA=record
A,B,C,D:integer;
end;

procedure abc(s:TypeA);
begin

end;

procedure abcEx(const s:TypeA);
begin

end;

procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
   Tick1,Tick2:DWORD;
   A:TypeA;
begin
Tick1:=GetTickCount;
for i:=0 to 1000000000 do abc(A);
Tick1:=GetTickCount-Tick1;

Tick2:=GetTickCount;
for i:=0 to 1000000000 do abcEx(A);
Tick2:=GetTickCount-Tick2;

showmessage(inttostr(Tick1)+" "+inttostr(Tick2));
end;

Учти пример еще без Managed типов.


 
{RASkov} ©   (2008-03-02 19:48) [22]

Дайте поймаю мысль...

> Разница есть.

С таким кодом:
procedure abc(i: integer);
begin
//по значению
end;

procedure abcEx(const i: integer);
begin
//по ссылки
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
  Tick1,Tick2:DWORD;
begin
 Tick1:=GetTickCount;
 for i:=0 to 100000000 do abc(5);
 Tick1:=GetTickCount-Tick1;

 Tick2:=GetTickCount;
 for i:=0 to 100000000 do abcEx(5);
 Tick2:=GetTickCount-Tick2;

 showmessage(inttostr(Tick1)+" "+inttostr(Tick2));
end;
Тоже есть.... в 3 раза... с конст итегер быстрее.... как же понять [7]?


 
oxffff ©   (2008-03-02 20:05) [23]


> procedure abcEx(const i: integer);
> begin
> //по ссылки
> end;


Увы. Это не по ссылке. см. Delphi help


 
oxffff ©   (2008-03-02 20:09) [24]


> как же понять [7]?


procedure abc(i: integer);
begin
end;

procedure abcEx(const i: integer);
begin
end;

Этот код исполняется идентично.


 
{RASkov} ©   (2008-03-02 20:16) [25]

> [24] oxffff ©   (02.03.08 20:09)
> Этот код исполняется идентично.

Как же идентично, а по времени выполнения - поразному?


 
oxffff ©   (2008-03-02 20:37) [26]


> {RASkov} ©   (02.03.08 20:16) [25]


Поменяй вызов.
цикл abc(5);
цикл abcEx(5);

цикл abcEx(5);
цикл abc(5);


 
oxffff ©   (2008-03-02 20:38) [27]

У меня
Вариант 1
1094 abc
1141 abcEX

Вариант 2
1094 abcEX
1140 abc


 
{RASkov} ©   (2008-03-02 20:46) [28]

> [27] oxffff ©   (02.03.08 20:38)

Ну фик знает)

procedure abc(i: integer);
begin
//ii cia?aie?
end;

procedure abcEx(const i: integer);
begin
//ii nnueee
end;

procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
 Tick1,Tick2:DWORD;
begin
Tick1:=GetTickCount;
for i:=0 to 100000000 do abc(555);
Tick1:=GetTickCount-Tick1;

Tick2:=GetTickCount;
for i:=0 to 100000000 do abcEx(555);
Tick2:=GetTickCount-Tick2;

showmessage(inttostr(Tick1)+" - "+inttostr(Tick2));
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:Integer;
 Tick1,Tick2:DWORD;
begin
Tick1:=GetTickCount;
for i:=0 to 100000000 do abcEx(555);
Tick1:=GetTickCount-Tick1;

Tick2:=GetTickCount;
for i:=0 to 100000000 do abc(555);
Tick2:=GetTickCount-Tick2;

showmessage(inttostr(Tick1)+" - "+inttostr(Tick2));
end;

---------------------------
Button1Click
922 - 297
---------------------------
Button2Click
485 - 906
---------------------------


 
oxffff ©   (2008-03-02 20:49) [29]


> RASkov} ©   (02.03.08 20:46) [28]


Попробуй именно в одной процедуре.
Один раз запустил зафиксировал.
Поменял, запустил, зафиксировал.


 
{RASkov} ©   (2008-03-02 21:03) [30]

---------------------------
Project1
---------------------------
(abcEx)266 - (abc)906
---------------------------
OK  
---------------------------

---------------------------
Project1
---------------------------
(abc)860 - (abcEx)312
---------------------------
OK  
---------------------------
?? :) Я уже по всякому перепробывал и все равно с конст быстрее....

вот еще результаты:
--begin test1--
abc - 907, abcEx 312
abc - 906, abcEx 313
abc - 907, abcEx 312
abc - 922, abcEx 297
abc - 922, abcEx 297
--end test1 begin test2--
abc - 250, abcEx 875
abc - 266, abcEx 859
abc - 250, abcEx 875
abc - 266, abcEx 859
abc - 250, abcEx 875
--end test2--


 
{RASkov} ©   (2008-03-02 21:07) [31]

Вот целиком модуль
unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var Form1: TForm1;

implementation
{$R *.dfm}

procedure abc(i: integer);
begin
//ii cia?aie?
end;

procedure abcEx(const i: integer);
begin
//ii nnueee
end;

procedure Test1;
var i:Integer;
 Tick1,Tick2:DWORD;
begin
 Tick1:=GetTickCount;
 for i:=0 to 100000000 do abc(555);
 Tick1:=GetTickCount-Tick1;

 Tick2:=GetTickCount;
 for i:=0 to 100000000 do abcEx(555);
 Tick2:=GetTickCount-Tick2;

 Form1.Memo1.Lines.Add(Format("abc - %3d, abcEx %3d", [Tick1, Tick2]));
end;

procedure Test2;
var i:Integer;
 Tick1,Tick2:DWORD;
begin
 Tick1:=GetTickCount;
 for i:=0 to 100000000 do abcEx(555);
 Tick1:=GetTickCount-Tick1;

 Tick2:=GetTickCount;
 for i:=0 to 100000000 do abc(555);
 Tick2:=GetTickCount-Tick2;

 Form1.Memo1.Lines.Add(Format("abc - %3d, abcEx %3d", [Tick1, Tick2]));
end;

procedure TForm1.Button1Click(Sender: TObject);
var N: Integer;
begin
 Form1.Memo1.Lines.Add("--begin test1--");
 for N:=0 to 4 do begin Test1; sleep(100); end;
 Form1.Memo1.Lines.Add("--end test1 begin test2--");
 for N:=0 to 4 do begin Test2; sleep(100); end;
 Form1.Memo1.Lines.Add("--end test2--");
end;

procedure TForm1.Button2Click(Sender: TObject);
var i:Integer;
Tick1,Tick2:DWORD;
begin
 Tick1:=GetTickCount;
 for i:=0 to 100000000 do abc(555);
 Tick1:=GetTickCount-Tick1;

 Tick2:=GetTickCount;
 for i:=0 to 100000000 do abcEx(555);
 Tick2:=GetTickCount-Tick2;

 showmessage(inttostr(Tick1)+" - "+inttostr(Tick2));
end;

end.

Вообщем нового, как я ни старался, из этой ветки я не узнал :( А так все началось интересно.. :)


 
Loginov Dmitry ©   (2008-03-02 21:09) [32]

> Опять заблуждение, хочешь пример?


Вообще-то ранее решь шла именно о Default, как параметре целого типа. Никакие TypeA не фигурировали.

Да и в [20] пример некорректный. showmessage там ни о чем не говорит.


 
Anatoly Podgoretsky ©   (2008-03-02 21:10) [33]

> oxffff  (02.03.2008 20:49:29)  [29]

Зачем измерять обращение к пустой функции, основные затраты как раз внутри.


 
Loginov Dmitry ©   (2008-03-02 21:13) [34]

> Зачем измерять обращение к пустой функции, основные затраты
> как раз внутри.


Кстати да, на ассемблере оба участка кода абсолютно одинаковые :)


 
{RASkov} ©   (2008-03-02 21:18) [35]

> Зачем измерять обращение к пустой функции, основные затраты
> как раз внутри.

Вот другое дело, я что-то сразу и не сообразил

procedure abc(i: integer);
begin
 Form1.Tag:=I*Random(I);
end;

procedure abcEx(const i: integer);
begin
 Form1.Tag:=I*Random(I);
end;

--begin test1--
abc -   703, abcEx -   687
abc -   687, abcEx -   703
abc -   688, abcEx -   703
abc -   703, abcEx -   687
abc -   687, abcEx -   688
--end test1 begin test2--
abc -   734, abcEx -   688
abc -   735, abcEx -   687
abc -   735, abcEx -   687
abc -   734, abcEx -   703
abc -   734, abcEx -   703
--end test2--

Получается одинаково.... Странно все это :)


 
oxffff ©   (2008-03-02 21:25) [36]


> Loginov Dmitry ©   (02.03.08 21:09) [32]
> > Опять заблуждение, хочешь пример?
>
>
> Вообще-то ранее решь шла именно о Default, как параметре
> целого типа. Никакие TypeA не фигурировали.
>
> Да и в [20] пример некорректный. showmessage там ни о чем
> не говорит.


А ты оптимизатор отключи. И тогда тебе станет все понятно.


 
oxffff ©   (2008-03-02 21:27) [37]


> Anatoly Podgoretsky ©   (02.03.08 21:10) [33]


Отключите оптимизатор, чтобы компилятор не искал зависимости.


 
Loginov Dmitry ©   (2008-03-02 21:27) [38]

> Получается одинаково.... Странно все это :)


Прикол в том, что компилятор "забил" на директиву const и передал I по значению :)


 
Anatoly Podgoretsky ©   (2008-03-02 21:30) [39]

> oxffff  (02.03.2008 21:27:37)  [37]

Зачем, меня эти тесты не интересуют


 
Loginov Dmitry ©   (2008-03-02 21:31) [40]

> А ты оптимизатор отключи. И тогда тебе станет все понятно.


А ты сам сперва попробуй!



Страницы: 1 2 3 вся ветка

Текущий архив: 2008.03.30;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.037 c
2-1204223376
arreke
2008-02-28 21:29
2008.03.30
Отправить письмо на email


2-1204610265
wasko
2008-03-04 08:57
2008.03.30
TFileStream


2-1204026313
Ultimate
2008-02-26 14:45
2008.03.30
Чтение данных системы...


15-1203177531
Alien1769
2008-02-16 18:58
2008.03.30
Интересная ошибка


15-1203336490
Andy BitOff
2008-02-18 15:08
2008.03.30
Новый тип потокового видео