Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.03.30;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.034 c
4-1178095379
Ma[X]iM
2007-05-02 12:42
2008.03.30
Получение массива пикселей по хендлу картинки


2-1204487900
Lamer666
2008-03-02 22:58
2008.03.30
DBGridEh и поле с авто просчетом


15-1202826268
Real
2008-02-12 17:24
2008.03.30
Как обломать wine?


2-1204321453
alexnmsk
2008-03-01 00:44
2008.03.30
Компонент на основе TActionList


15-1203418335
БарЛог
2008-02-19 13:52
2008.03.30
Использование переменных окружения в Java





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский