Текущий архив: 2004.10.24;
Скачать: CL | DM;
ВнизКто-нибудь сможет сходу определить причину ошибки? :) Найти похожие ветки
← →
Piter © (2004-10-04 23:10) [0]Вот такой я маленький тест придумал... Кто сможет без Дельфей объяснить следующую ситуацию:
Такой код работает:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
end;
end;
А вот такой код НЕ работает:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
end;
Вопрос - почему? :)
P.S. На ум приходит очевидный ответ... но почему же первый пример работает?
← →
panov © (2004-10-04 23:13) [1]Всё просто...
← →
panov © (2004-10-04 23:14) [2]Edit: TEdit - обрабатывает компилятор.
← →
Ломброзо © (2004-10-04 23:20) [3]> Parent := self;
чей блин парент?
← →
Piter © (2004-10-04 23:24) [4]panov © (04.10.04 23:14) [2]
Edit: TEdit - обрабатывает компилятор
не понял твою идею :)
Что значит обрабатывает компилятор? Типа другие строки компилятор не обрабатывает? :)
← →
_silver © (2004-10-04 23:30) [5]
>var
> ArrayEdit: array of TEdit;
Может я и не прав, но это динамический массив.
Надо SetLength
← →
jack128 © (2004-10-04 23:33) [6]Тя разговор с GuAV навел на эти эксперементы?? Ну так у него(у GuAV) в анкете есть ответ на твой вопрос. Нужно лищь глянуть в окно CPU..
← →
_silver © (2004-10-04 23:35) [7]Извиняюсь.
ArrayEdit[0].Parent := self;
← →
_silver © (2004-10-04 23:39) [8]
>_silver © (04.10.04 23:30) [5][Ответить]
>
>>var
>> ArrayEdit: array of TEdit;
>
>Может я и не прав, но это динамический массив.
> Надо SetLength
Ещё раз прошу прошения.
← →
Cobalt © (2004-10-04 23:40) [9]Вообще-то код с логической точки зрения некорректный - если компилятор и может (в принципе), то с логической точки зрения надо сначала проинициализировать переменную, а потом уже делать
with AlreadyInitialisedClassVariable do
← →
Cobalt © (2004-10-04 23:42) [10]пардон, не закончил фразу - компилятор может, в принципе, разрулить такую ситуацию.
Но разработчики переложили это на плечи программистов.
← →
Ломброзо © (2004-10-04 23:47) [11]Cobalt © (04.10.04 23:40) [9]
ИМХО под локальные переменные просто выделяется кусок стека. А посему при вызове делать инициализацию этого куска нулём - это лишний такт. Вот пущай программист сам обнуляет, если ему нужно.
← →
jack128 © (2004-10-04 23:48) [12]Ломброзо © (04.10.04 23:47) [11]
ИМХО под локальные переменные просто выделяется кусок стека
не всегда. Пример с edit"ом(первый) тому подтверждение
← →
_silver © (2004-10-04 23:50) [13]Работает так:
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
и так:
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do
begin
Parent := self;
end;
← →
_silver © (2004-10-04 23:52) [14]Это я ктому, что компилятор может ещё не знать о ArrayEdit[0].Parent в первом варианте.
← →
_silver © (2004-10-04 23:57) [15]Т.е. конструкция width ArrayEdit[0] ещё не определена.
← →
Ломброзо © (2004-10-04 23:58) [16]jack128 © (04.10.04 23:48) [12]
А что там в первом примере? Указатель нулю равен? дык это просто повезло.
← →
jack128 © (2004-10-05 00:04) [17]Если с асм"ом не очень, то озвучу явно - в первом примере переменной Edit вообще не существует. И строка with Edit компилятором вообщ игнорируется. Для обращения к SetParent используется результат TEdit.Create(Self)
Во втором примере начало в регистры проца закачивается ArrayEdit[0] (мусор)(эквивалент with ArratEdit[0] do), потом в память записывается результат TEdit.Create(Self), а потом уже берется наша копия ArrayEdit[0] (которая мусор) и используется для SetParent
Ломброзо © (04.10.04 23:58) [16]
Указатель нулю равен? дык это просто повезло.
нету указателя как такового. Нету переменной Edit вообще. вот для такого кода
:
procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
Top := 10;
end;
end;
то что храниться в esi можно назвать переменной Edit, но не для примера Piter"a
← →
Ломброзо © (2004-10-05 00:14) [18]Аспасиба. Я действительно в ассемблере мало, но на грабли с неинициализированным указателем на объект в теле функции в ++, как и всякому нормальному человеку, наступать приходилось )
← →
GuAV © (2004-10-05 00:31) [19]А теперь версия ответа на этот вопрос от GuAV :)
Откомпилируйте обе версии.
Слева вы видете то что попало в конечный ехе синими кружечками отмечено.
в случае с массивом with попало в ехе. это как бы создало локальную переменную.
в другом случае Edit и есть та переменная
регистры или память не важно ({$O-} - и будет оно в стеке), но Ctrl+Alt+ тут конечно проясняет.
← →
GuAV © (2004-10-05 00:33) [20]
> Ctrl+Alt+ тут конечно проясняет.
Ctrl+Alt+С естественно, не Del :)
← →
_silver © (2004-10-05 00:47) [21]О чём вы рассуждаете?
ArrayEdit: array of TEdit - дин масив.
На этапе
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
ещё не известно что будет находиться в ArrayEdit[0].
Вся конструкция
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
просто не коректна.
← →
jack128 © (2004-10-05 01:02) [22]_silver © (05.10.04 0:47) [21]
ну и что?? with Edit do - тоже не определен, а тем немение работает.
ГуАВ все правельно объяснил.
← →
Piter © (2004-10-05 01:10) [23]jack128 © (04.10.04 23:33) [6]
лищь глянуть в окно CPU..
ну дык. Только вот:
> Кто сможет без Дельфей объяснить следующую ситуацию
:)))
Я вот о чем подумал. Отстранимся от ассемблера.
С точки зрения разработчика, получается, что в первом случае под with подразумевается именно реальный текущий Edit.
То есть, можно написать:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
with Edit do
begin
Edit := TEdit.Create(self);
Free;
Edit := TEdit.Create(self);
Parent := self;
end;
end;
И все будет ок. В последней строчкеParent := self;
имеется в виду именно реальный Edit. Не тот Edit который был на начале With (мусор). И не тот Edit, который был создан первично. А именно актуальный на текущий момент Edit. Вот то, что показывает Watch List [Pointer(Edit)] - к тому и будет обращение .
Получается аналог этого кода:procedure TForm1.Button1Click(Sender: TObject);
var
Edit: TEdit;
begin
Edit := TEdit.Create(self);
Edit.Free;
Edit := TEdit.Create(self);
Edit.Parent := self;
end;
В случае втором же все обстоит иначе. Если следовать приведенной выше логике, то код:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
end;
Должен быть эквивалентен:procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
Иначе говоря, если есть обращение:with SomeClass do
SomeMethod;
то если у SomeClass есть метод SomeMethod, то такая конструкция ничем не должна отличаться от простого:SomeClass.SomeMethod
Но во втором случае компилятор не так делает. Он не тупо обращается к экземпляру класса. Он обращается туда, куда указывал ArrayEdit[0] на начало with.
Ведь with не что иное как просто упрощения записи, чтобы было понятнее.
То есть, если мы пишем:with SomeClass do
begin
SomeMethod1;
SomeMethod2;
SomeMethod3;
SomeMethod4;
end;
То мы как бы можем рассчитывать, что это тоже самое, что и такой код:SomeClass.SomeMethod1;
SomeClass.SomeMethod2;
SomeClass.SomeMethod3;
SomeClass.SomeMethod4;
А получается, что не совсем так...
Во втором случае мне кажется компилятор ведет себя немного не так, как нужно. Кто как считает? :)
P.S. Сейчас мне кто-нибудь точно припомнит IS :)))
P.S.S. Сам сейчас прочитал, что написал... блин, надо учиться излагать мысли, как-то все коряво получилось.
← →
Piter © (2004-10-05 01:11) [24]_silver © (05.10.04 0:47) [21]
О чём вы рассуждаете?
ArrayEdit: array of TEdit - дин масив.
На этапе
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
ещё не известно что будет находиться в ArrayEdit[0].
Вся конструкция
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
Parent := self;
end;
просто не коректна.
Ладно, получается что:
"О чём вы рассуждаете?
Edit: TEdit - это экземпляр класса
На этапе
with Edit do
ещё не известно что будет находиться в Edit.
Вся конструкция
with Edit do
begin
Edit := TEdit.Create(self);
Parent := self;
end;
просто не коректна."
Только вопрос - почему работает то? :)
← →
_silver © (2004-10-05 01:17) [25]Дин масив ссылок на что-то типа TEdit допустим.
with ArrayParent[0] - ожидается использование объекта типа TEdit, но ещё не создан.
Поэтому в блоке begin .. end свойство Parent(класса TEdit) неизвестно.
З.Ы.
Это тоже что сказал GuAV тока с объяснением.
← →
Knight © (2004-10-05 01:19) [26]Не знаю как вы, а я всегда сначала делаю Create, а только после этого уже юзаю with...
procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do begin
Parent := self;
end;
end;
← →
GuAV © (2004-10-05 01:20) [27]Если with использованна с переменной, полем записи, то то что в with не требует вычислений и with вносит чисто синтаксические изменения.
Если with использованна с функцией, методом класса, и т.д. то то что в with требует вычислений, результат которых фактически заносится в новую переменную (которая в прочем может быть и в регистрах - но это уже следствие оптимиации).
> То мы как бы можем рассчитывать, что это тоже самое, что
> и такой код:
нет. но к записи это применимо.
← →
jack128 © (2004-10-05 01:22) [28]Piter © (05.10.04 1:10) [23]
Piter © (05.10.04 1:10) [23]
То есть, если мы пишем:
with SomeClass do
begin
SomeMethod1;
SomeMethod2;
SomeMethod3;
SomeMethod4;
end;
То мы как бы можем рассчитывать, что это тоже самое, что и такой код:
SomeClass.SomeMethod1;
SomeClass.SomeMethod2;
SomeClass.SomeMethod3;
SomeClass.SomeMethod4;
А получается, что не совсем так...
Как я понял из GuAV © (05.10.04 0:31) [19] из асм"а реально with SameVar do делает следующее
для кода
begin
with SameVar do
begin
DoSamething1;
DoSamething2;
DoSamething3;
end;
end;
компилятор генерит примерно следующее
для переменных в дин памяти:
var
LocalVar: TSameType;
begin
LocalVar := SameVar;
LocalVar.DoSamething1;
LocalVar.DoSamething2;
LocalVar.DoSamething3;
end;
а для любых других - ничего не делается!! Например, если ты заменишь дин массив - статическим, то все будет работать..
Piter © (05.10.04 1:10) [23]
> Кто сможет без Дельфей объяснить следующую ситуацию
Я бы ответил (я собственно так и ответил) не правельно, насчет оптимизации с выкидыванием ненужного Edit"a
← →
GuAV © (2004-10-05 01:29) [29]
> для переменных в дин памяти:
Не только в дин. памяти, см. [27] .
Хороший пример
with MyArray[Random(5)] do
begin
A:=5; B:=7;
end;
не то же что
MyArray[Random(5)].A:=5;
MyArray[Random(5)].B:=7;
но если заменить Random(5) на 5, то with не делает разницы.
← →
_silver © (2004-10-05 01:35) [30]GuAV © (05.10.04 1:29) [29]
Если MyArray : array of recor a : Integer; b : Integer; end;
..
with MyArray[Random(5)] do
begin
A:=5; B:=7;
end;
то еррор, как раз о то о чём говорил я.
← →
GuAV © (2004-10-05 02:10) [31]я имел ввиду стат массив.
← →
Ihor Osov'yak © (2004-10-05 02:43) [32]> Кто-нибудь сможет сходу определить причину ошибки? :)
Корень ошибки - в упорном нежелании обращать внимание на хинты и варнинги компилятора.
Зы. странно, что борланды вообще такую конструкцию считают синтастически допустимой...
← →
1008 © (2004-10-05 09:14) [33]Объявить массив глобально - должно работать, во всяком случае у меня подобные конструкции работают. Правда никогда не пробовал в качестве предка задавать сам компонент.
← →
Fay © (2004-10-05 09:18) [34]2 1008 © (05.10.04 09:14) [33]
> Правда никогда не пробовал в качестве предка задавать сам
> компонент.
Это Вы о чём?
← →
1008 © (2004-10-05 09:28) [35]Fay © (05.10.04 09:18) [34]
я делаю так:
var
RichEditArray:array of TRichEdit;
...
Procedure ...
var
i,n:integer;
begin
...
SetLehgth(RichEditArray,n);
for i:=0 to n-1 do begin
RichEditArray[i]:=TRichEdit.Create(Self);
RichEditArray[i].Parent:=Panel;//к примеру
end;
← →
Fay © (2004-10-05 09:31) [36]Как Вы делаете я понял. Но в пику чему этот пример?
← →
SergP. (2004-10-05 09:35) [37]Могу конечно ошибиться, так как сейчас не могу запустить Delphi и поэкспериментировать с обоими примерами, а также попробовать статический массив.
with ArrayEdit[0]
Но имхо здесь автор сабжа вместо элемента массива получает указатель на сам массив.
← →
1008 © (2004-10-05 09:40) [38]Fay © (05.10.04 09:31) [36]
Никому ни в чью пику я ничего не делаю. Я просто сказал как я делаю, чтоб не было ошибок.
Piter © (04.10.04 23:10)
А вот такой код НЕ работает:
procedure TForm1.Button1Click(Sender: TObject);
var
ArrayEdit: array of TEdit;
begin
setlength(ArrayEdit, 1);
with ArrayEdit[0] do
begin
ArrayEdit[0] := TEdit.Create(self);
ArrayEdit[0].Parent := self;
end;
end;
вот так работает, хотя это уже указали
← →
Fay © (2004-10-05 09:45) [39]Вы, видимо, думаете, что в качестве
Self
выступаетArrayEdit[0]
? Уверен, что это не так, чтоSelf
в данном случае - экземплярTForm1
.
← →
SergP. (2004-10-05 09:46) [40]
> [37] SergP. (05.10.04 09:35)
Все-таки я ошибся.
Такой код:
ArrayEdit[0] := TEdit.Create(self);
with ArrayEdit[0] do Parent := self;
Работает.
Значит причина ошибки та что была уже неоднократно высказана.
← →
Гаврила © (2004-10-05 10:44) [41]Забавно
я, честно говоря, думал, что with отметается еще на этапе синтаксического разбора, оказывается нет
← →
DiamondShark © (2004-10-05 11:42) [42]
> Ведь with не что иное как просто упрощения записи, чтобы
> было понятнее.
Ничего подобного.
> P.S. Сейчас мне кто-нибудь точно припомнит IS :)))
Ну, ты в курсе.
← →
Piter(Ne doma) (2004-10-05 12:13) [43]Корень ошибки - в упорном нежелании обращать внимание на хинты и варнинги компилятора
никаких предупреждение компилятор НЕ ПИШЕТ
← →
GuAV © (2004-10-05 12:30) [44]
> я, честно говоря, думал, что with отметается еще на этапе
> синтаксического разбора, оказывается нет
Иногда отметается иногда нет см. примеры в [0]
Кстати, я обычно стараюсь не писать такое with которое будет отметено. т.е. with ArrayEdit[0] do напишу, а with Edit do заменю на Edit.* ; Edit.* ; ...
> Зы. странно, что борланды вообще такую конструкцию считают
> синтастически допустимой...
О чём это Вы ?
← →
Суслик © (2004-10-05 12:36) [45]смерть with.
я перестал его использовать еще на досе когда писал - пока не жалею.
← →
1008 © (2004-10-05 12:38) [46]Суслик © (05.10.04 12:36) [45]
иногда бывает удобно
← →
Суслик © (2004-10-05 12:42) [47]
> иногда бывает удобно
не будем начинать холи вор, поэтому соглашусь:))
но я не пользуюсь.
← →
Sandman25 © (2004-10-05 12:44) [48][47] Суслик © (05.10.04 12:42)
Нет, надо было ответить: "Мне всегда неудобно". И никто оспорить не сможет :)
← →
вразлет © (2004-10-05 12:45) [49]-Скажите, а ваучер это ценная бумага?
-В жизни каждого человека бывает минуты, когда любая бумажка становится очень ценной(с)
← →
DiamondShark © (2004-10-05 13:17) [50]
> Суслик © (05.10.04 12:36) [45]
> смерть with.
Смерть ламерам.
> я перестал его использовать еще на досе когда писал - пока
> не жалею.
И это правильно. Чего не понимаешь -- лучше не использовать.
← →
GuAV © (2004-10-05 13:25) [51]
> Смерть ламерам.
Не скажите. Без with всегда можно обойтисьvar
можно заменить на
A: TMyStrucType;
begin
with A do
begin
B;
C;
end;begin
А конструкцию типа
A.B;
A.C;begin
заменить на
with TmyType.Create do
begin
B;
C;
end;var
localvar: TmyType;
begin
localvar:=TmyType.Create;
localvar.B;
localvar.C;
Эти замены будут чисто синтаксическими и не влияют на результат компиляции.
Лучше не использовать with чем ошибочно его применять.
← →
Игорь Шевченко © (2004-10-05 13:29) [52]GuAV © (05.10.04 13:25) [51]
> Без with всегда можно обойтись
Можно. Но не всегда удобно. Пример в студии
var
PrefilterExpressionValue: string;
....
with FPrefilterClass.Create(AOwner) do
try
Mr := ShowModal;
if Mr = mrOk then
PrefilterExpressionValue := PrefilterExpression;
finally
Free;
end;
← →
jack128 © (2004-10-05 13:38) [53]> Без with всегда можно обойтись
всегда можно обойтись без Exit, Break, параметров по умолчанию, циклов for/repeat, без классов/объектов в конце концов ;-)
> Лучше не использовать with чем ошибочно его применять.
ну так это относиться не только к with ;-)
← →
KSergey © (2004-10-05 13:40) [54]> [52] Игорь Шевченко © (05.10.04 13:29)
Маааленькая ремарочка.
Я что-то стал склоняться к мысли, что в подобных конструкциях есть смысл использоватьwith FPrefilterClass.Create(nil) do
Все равно есть явный код уничтожения, так стоит ли лишний раз назначать родителя (которому будет слаться уведомление при создании/разрушении)?
← →
KSergey © (2004-10-05 13:41) [55]Не родителя - owner"а (владельца), конечно
← →
Игорь Шевченко © (2004-10-05 13:59) [56]KSergey © (05.10.04 13:40) [54]
> так стоит ли лишний раз назначать владельца
Стоит, как минимум, если в создаваемом классе имеется явное или неявное обращение к свойствам/метолам владельца.
← →
DiamondShark © (2004-10-05 14:12) [57]
> Стоит, как минимум, если в создаваемом классе имеется явное
> или неявное обращение к свойствам/метолам владельца.
Тогда этот класс не должен допускать параметр nil в конструкторе.
← →
Суслик © (2004-10-05 14:12) [58]
> [50] DiamondShark © (05.10.04 13:17)
> Смерть ламерам.
в своем стиле :))) Я тебе лично что-то сказал, или with твой близкий родственник?
Для меня лично with уменьшает наглядность кода. А т.к. у меня его (кода) много (порядка 1млн строк), то этот факт для меня весьма критичен. Есть моменты, когда я могу его использовать. Но они чрезвычайно редки.
← →
Игорь Шевченко © (2004-10-05 14:14) [59]DiamondShark © (05.10.04 14:12) [57]
> Тогда этот класс не должен допускать параметр nil в конструкторе.
В этом случае может действовать поведение по умолчанию. Все зависит от задачи.
← →
KSergey © (2004-10-05 14:23) [60]> [56] Игорь Шевченко © (05.10.04 13:59)
> Стоит, как минимум, если в создаваемом классе имеется явное
> или неявное обращение к свойствам/метолам владельца.
Вы меняете условия ;) По сути задаете такие, где это необходимо, что не имеет никакого отношения к эффективности ;)
К стати, о неявном: что-то на ум ничего не приходит...
← →
Игорь Шевченко © (2004-10-05 14:27) [61]KSergey © (05.10.04 14:23) [60]
> Вы меняете условия ;) По сути задаете такие, где это необходимо,
> что не имеет никакого отношения к эффективности ;)
А о какой эффективности может идти речь в этом случае ? :)
> К стати, о неявном: что-то на ум ничего не приходит...
procedure TWinControl.CreateWnd;
....
if (WndParent = 0) and (Style and WS_CHILD <> 0) then
if (Owner <> nil) and (csReading in Owner.ComponentState) and
(Owner is TWinControl) then
WndParent := TWinControl(Owner).Handle
else
raise EInvalidOperation.CreateFmt(SParentRequired, [Name]);
:))
← →
KSergey © (2004-10-05 14:35) [62]> [61] Игорь Шевченко © (05.10.04 14:27)
Ну в приведенном коде вполне допустима ситуация, когда nil. Хотя согласен, по сути оно.
> [61] Игорь Шевченко © (05.10.04 14:27)
> А о какой эффективности может идти речь в этом случае ?constructor TComponent.Create(AOwner: TComponent);
begin
FComponentStyle := [csInheritable];
if AOwner <> nil then AOwner.InsertComponent(Self);
end;
Ну и ответная часть в деструкторах.
В коде
> [52] Игорь Шевченко © (05.10.04 13:29)
я не вижу смысла в Owner как таковом, а потому выполнение выделенного участока кода считаю никчемным кроме случаем, когда это необходимо по каким-либо (признаюсь, редко, на мой взгляд, встречающимся) причинам. Хотя предлагаю не спорить о самих причинах, их частоте возникновения и т.п. - это лишь от ситуации зависит, согласитесь, однако, думаю, вы так же согласитесь, что имеет смысл писать тут nil, когда нет явной необходимости в обратном, при этом nil сэкономит нам несколько машинных тактов ;)
← →
Игорь Шевченко © (2004-10-05 15:11) [63]KSergey © (05.10.04 14:35) [62]
> В коде
>
> > [52] Игорь Шевченко © (05.10.04 13:29)
>
> я не вижу смысла в Owner как таковом
Потому что ты не видишь код создаваемого класса :)
> > А о какой эффективности может идти речь в этом случае
> ?
>
> constructor TComponent.Create(AOwner: TComponent);
> begin
> FComponentStyle := [csInheritable];
> if AOwner <> nil then AOwner.InsertComponent(Self);
> end;
Все равно, не понимаю, о какой эффективности идет речь.
← →
KSergey © (2004-10-05 15:20) [64]О повышении быстродействия. Или это не эффективность? Может я термины неудачные применяю?
← →
Anatoly Podgoretsky © (2004-10-05 15:42) [65]О каклм повышении быстродействия может идти речь.
Мухи отдельно, котлеты отдельно.
← →
Игорь Шевченко © (2004-10-05 15:44) [66]KSergey © (05.10.04 15:20) [64]
> О повышении быстродействия.
Я сильно сомневаюсь, что в данной конкретной конструкции повышение быстродействия играет хоть мало-мальски заметную роль.
← →
Anatoly Podgoretsky © (2004-10-05 15:45) [67]Игорь Шевченко © (05.10.04 15:44) [66]
А оно вообще не имеет отношения к быстродействию :-)
← →
Игорь Шевченко © (2004-10-05 15:49) [68]Anatoly Podgoretsky © (05.10.04 15:45) [67]
Насколько я понимаю, предлагается повышение быстродействия за счет исключения вызова метода InsertComponent (и RemoveComponent, соответственно).
← →
Sandman25 © (2004-10-05 15:49) [69][66] Игорь Шевченко © (05.10.04 15:44)
Создается процедура. По умолчанию она без параметров. Если понадобился параметр, он добавляется в определение и вызов. Никто не описывает процедуру с 10 параметрами, которые никогда не понадобятся.
Имеем метод с обязательным параметром, который в конкретном случае не нужен. Зачем передавать что-нибудь кроме nil? Зачем замедлять работу программу добавлением/удалением контрола в/из список?
[67] Anatoly Podgoretsky © (05.10.04 15:45)
Ненужные действия замедляют работу. Особенно если они совершаются в цикле.
← →
Суслик © (2004-10-05 15:54) [70]
> Ненужные действия замедляют работу. Особенно если они совершаются
> в цикле.
:)))
О замедлении можно говорить в одном случае - когда проведен опыт "до" и "после" с замерами и с решением о том важно ли быстродействие в данном конкретном случае или нет.
← →
Sandman25 © (2004-10-05 15:57) [71][70] Суслик © (05.10.04 15:54)
A; B; C
всегда будет медленнее чем
A; A1; B; С1; С
← →
Суслик © (2004-10-05 16:15) [72]
> [71] Sandman25 © (05.10.04 15:57)
> всегда будет медленнее чем
Медленнее и чудовищно медленнее разные вещи.
"Медленнее" не важно в большинстве случаев.
"Чудовищно медленнее" важно почти всегда.
При каком замедлении ставить эпитет "чудовищно" каждый решает сам (или за него реает начальник). Все зависит от ситуации. Чаще твое личное время важнее и дороже.
← →
Игорь Шевченко © (2004-10-05 16:18) [73]Sandman25 © (05.10.04 15:49) [69]
> Имеем метод с обязательным параметром, который в конкретном
> случае не нужен.
А кто сказал, что он не нужен ?
> Ненужные действия замедляют работу. Особенно если они совершаются
> в цикле.
Я понимаю желание пофлеймить, но исходный код, из-за которого развязалась дискуссия, тоже бы неплохо глянуть.
← →
Sandman25 © (2004-10-05 16:22) [74][72] Суслик © (05.10.04 16:15)
Я считаю, что для того, чтобы программист сделал неоптимально, всегда должна быть причина. Делать медленнее, чем можешь, только потому, что будет не намного медленнее, могуть только саботажники.
PS. "Я сделал медленнее, потому что привык передавать параметром форму" или "потому что в будущем может понадобиться обратиться к методу владельца" - причины.
PPS. "nil" - короче, чем "MyForm" :)
← →
Sandman25 © (2004-10-05 16:23) [75][73] Игорь Шевченко © (05.10.04 16:18)
Я понимаю, что в данном случае следует указывать конкретный параметр. Меня удивляет Ваше нежелание признать, что очень часто лучше указывать именно nil.
← →
Суслик © (2004-10-05 16:26) [76]
> [74] Sandman25 © (05.10.04 16:22)
А я считаю, что все зависит от условий и целей работы.
Оптимизировать нужно только критичные места. Зачастую наглядность кода важнее оптимальности. Чем важнее? Да все тем же - деньгами: замеление на 23 мс не заметит никто, а ты, возможно допустивный в будущем при модификации ошибку по причине недопонимания заоптимизированного по самы помидоры кода, принесешь конторе определенный убыток. Пусть и не большой, но убыток - лишний потраченный час (блин, что я сейчас делаю :))) есть деньга...
← →
Sandman25 © (2004-10-05 16:33) [77][76] Суслик © (05.10.04 16:26)
Не об оптимизации разговор. Грубо говоря, чтобы написать
A := 1;
B := 2;
A := 2;
нужна причина. Кодер тратит время на написание третьей строки, потом другой кодер полчаса пытается понять, в чем же причина того, что третья строка была написана, потом третий кодер матерится, когда видит количество лишних строк, разбросанных по всему модулю...
Резюме: для ухудшения кода должна быть причина. Под ухудшением понимаем все, что угодно - от ненаглядности до глюкавости.
PS. Что аналогия некорректна, я понимаю.
← →
Суслик © (2004-10-05 16:34) [78]
> [77] Sandman25 © (05.10.04 16:33)
в этом согласен.
а мы разве про это говорили? наверное я что-то не понял...
← →
Sandman25 © (2004-10-05 16:38) [79][78] Суслик © (05.10.04 16:34)
Боюсь, что и Игорь Шевченко тоже не понял, почему я написал свой пост.
1. Передача не nil в конструктор компонента замедляет работу.
2. Исходя из пункта 1, кодер вправе рассчитывать, что есть какая-то причина, почему передается не nil. Особенно, если учесть, что в качестве параметра можно передать все, что угодно, начиная от Application и заканчивая AnotherForm.HiddenButton.
← →
Anatoly Podgoretsky © (2004-10-05 16:49) [80]Sandman25 © (05.10.04 16:38) [79]
Если с тобой согласиться, то придется делать двойной комплект методов, с параметром и без. Вот тут тебе прогнозирую резкое замедление производительности, на время написания, на время тестирования и навремя поиска потом ошибок в программе.
Механизм с одним методом гарантирует как единообразие, так и отсутствие возможных ошибок, где передали, где нет, а использовать пытались.
Перенос анализа на НИЛ из метода добавления в другие методы, к тому же вызовет заметное замедление работы других частей иерархии.
← →
Игорь Шевченко © (2004-10-05 16:49) [81]Sandman25 © (05.10.04 16:23) [75]
> Я понимаю, что в данном случае следует указывать конкретный
> параметр
И это утверждение неверно :)
> Меня удивляет Ваше нежелание признать, что очень часто лучше
> указывать именно nil.
Зачем ? В своем посте [59] я сказал уже, что все зависит от задачи.
← →
Sandman25 © (2004-10-05 16:54) [82][80] Anatoly Podgoretsky © (05.10.04 16:49)
Мне кажется, что Вы меня не поняли. Я не призываю к overload, я призываю использовать nil в качестве параметра, если параметр не используется.
К тому же, это отлично сочетается с синтаксисом параметров по умолчанию, где для объектов может быть только nil.
[81] Игорь Шевченко © (05.10.04 16:49)
И это утверждение неверно :)
Вы сообщили, что в данном случае у Вас используется параметр, и у меня нет оснований Вам не верить, уж извините :)
Зачем ? В своем посте [59] я сказал уже, что все зависит от задачи.
Правильно. Но по умолчанию следует передавать nil (если все равно, что передавать). Это логично, быстро и понятно другим программистам :)
← →
Anatoly Podgoretsky © (2004-10-05 16:57) [83]В таком случае никакого повышения не наблюдается, без разницы кто передаст параметр, программист или компилятор, параметр все равно передается.
← →
Sandman25 © (2004-10-05 17:03) [84][83] Anatoly Podgoretsky © (05.10.04 16:57)
Тут уже проскакивал код из Create c проверкой на nil и вызовом InsertComponent.
В случае передачи nil InsertComponent не вызовется. Аналогично при удалении.
← →
Игорь Шевченко © (2004-10-05 17:08) [85]
> Правильно. Но по умолчанию следует передавать nil (если
> все равно, что передавать). Это логично, быстро и понятно
> другим программистам :)
Насчет логичности и понятности другим программистам лично я сильно сомневаюсь. Быстрота в данном случае не играет мало-мальски значимой роли.
← →
Sandman25 © (2004-10-05 17:11) [86][85] Игорь Шевченко © (05.10.04 17:08)
Насчет логичности и понятности другим программистам лично я сильно сомневаюсь
Имеете право. Я обычно разбираюсь с новым кодом с помощью метода обхода графа в ширину, а не глубину, и поэтому стараюсь сразу же понять, что передается параметром, то есть нажимаю Ctrl+клик и начинаю изучать эту самую форму. Жаль, конечно, что зря.
← →
Piter © (2004-10-05 23:16) [87]сразу хочу извиниться, что врываюсь тут к вам с оффтопом..
_silver © (05.10.04 1:17) [25]
with ArrayParent[0] - ожидается использование объекта типа TEdit, но ещё не создан.
Поэтому в блоке begin .. end свойство Parent(класса TEdit) неизвестно
НУ БЛИН!
А вwith Edit
разве не ожидается использование объекта TEdit??? Но ведь он то еще не создан и Parent Тоже неизвестно!!!!!!!
А пример то работает.
← →
GuAV © (2004-10-06 01:13) [88]О быстродействии говорить не следует.
см [51]. Эквивалентный код с with и без.
Когда речь идет о with речь идёт об удобстве/неудобстве или о понятности/непонятности кода.
← →
Ihor Osov'yak © (2004-10-06 01:41) [89]2 [43] Piter(Ne doma) (05.10.04 12:13)
> никаких предупреждение компилятор НЕ ПИШЕТ
Да, здесь я был не прав. Иногда случается. В принцыпе, свой постинг я делал чесно - "без делфи". Во вторых - здесь имхо - следовало бы генерить варниг как минимум (я был убежден, что генерится). И - см. ниже.
2 [44] GuAV © (05.10.04 12:30)
>> Зы. странно, что борланды вообще такую конструкцию считают
>> синтастически допустимой...
>О чём это Вы ?
изменение в теле with "подwith-нутой" переменной. Если чесно - я такого бы не написал даже при изрядной степени опьянения. Имхо, это (изменение в теле with "подwith-нутой" переменной) сродни попытки изменения переменой цыкла внутри цыкла. Что из этого может получиться - см. выше.
← →
GuAV © (2004-10-06 01:51) [90]Ihor Osov"yak © (06.10.04 01:41) [89]
Подумал, и вынужден с Вами согласится.
← →
Игорь Шевченко © (2004-10-06 11:26) [91]GuAV © (06.10.04 01:13) [88]
> Когда речь идет о with речь идёт об удобстве/неудобстве
> или о понятности/непонятности кода.
View|Debug windows|CPU
← →
Igorek © (2004-10-06 12:05) [92]> Ihor Osov"yak © (06.10.04 01:41) [89]
> изменение в теле with "подwith-нутой" переменной. Если чесно
> - я такого бы не написал даже при изрядной степени опьянения.
> Имхо, это (изменение в теле with "подwith-нутой" переменной)
> сродни попытки изменения переменой цыкла внутри цыкла.
Точно!
← →
Anatoly Podgoretsky © (2004-10-06 12:16) [93]Piter © (05.10.04 23:16) [87]
У тебя все работает, только изменяется содержимое регистра или временной переменой :-)
← →
GuAV © (2004-10-06 13:00) [94]Игорь Шевченко © (06.10.04 11:26) [91]
procedure With1; // breakpoint here
begin
with Form1.Memo1.Lines do
begin
Add("zzzzzzz");
Add("xxxxxxx");
end;
end;
procedure WithOut1;
var L: TStrings;
begin
L:=Form1.Memo1.Lines; // breakpoint here
L.Add("zzzzzzz");
L.Add("xxxxxxx");
end;
procedure With2;
begin
with TForm.Create(nil) do // breakpoint here
try
color:=clred;
finally
free;
end;
end;
procedure WithOut2;
var F: TForm;
begin
F:=TForm.Create(nil); // breakpoint here
try
F.color:=clred;
finally
F.free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
With1;
WithOut1;
With2;
WithOut2;
end;
В CPU я вижу только отличия которые связаны с тем что процедуры находится по разному смещению, инструкции абсолютно те же.
Страницы: 1 2 3 вся ветка
Текущий архив: 2004.10.24;
Скачать: CL | DM;
Память: 0.73 MB
Время: 0.036 c