Форум: "Начинающим";
Текущий архив: 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