Тема открыта по просьбе жителей Королевства и посвящена обсуждению вопросов оптимизации кода. Выставляйте свои лучшие и худшие тексты и не стесняйтесь их обсуждать. В споре рождается истина. Или, по крайней мере, оптимизация.
Всего в теме 737 сообщений
Добавить свое сообщение
Отслеживать это обсуждение
- Тестирование проекта. Отладка.
- Подводные камни
- Централизованная обработка ошибок
- Бета-тестирование
- Давайте учиться на ошибках.
- Почему программисты допускают ошибки?
- Автоматизированные тесты для GUI
- О системах контроля ошибок
№ 677 20-05-2009 05:06 | |
Oops! Я был неправ.
Посмотрел словарь.
Оказывается, английский не такой уж и чистый.
№ 676 20-05-2009 05:03 | |
Ответ на »сообщение 674« (Geo)
___________________________
>>> Cathetus
Ну вот! А в другой ветке только что о чистом английском проповедовали.
Значит это было чисто умозрительное высказывание :)
№ 675 20-05-2009 04:32 | |
Ответ на »сообщение 674« (Geo)
___________________________
Ну, не люблю я еще со времен школьной математики прописывать все промежуточные действия Почему бы тогда не пойти еще дальше и избавиться от еще одного лишнего оператора присваивания и написать процедуру: procedure NewPInteger(var P: PInteger; const DefaultValue: Integer = 0);
...
NewPInteger(P, 10); Т.е. возвращаемся к При ближайшем рассмотрении все навороты оказались не нужны ... В подавляющем большенстве случаев оказывается тоже самое
если нравится Delphi, то обязательно должен ненавидеть Си? ;-) А какие еще варианты могут быть? :)))
№ 674 20-05-2009 04:05 | |
Ответ на »сообщение 673« (Cepгей Poщин)
___________________________
>>> Такая экономность в количестве строчек кода характерна для C-шников
А что за противопоставление такое: типа, если нравится Delphi, то обязательно должен ненавидеть Си? ;-) Мне оба языка нравятся. И есть некоторые чисто сишные конструкции, которые я не прочь бы видеть и в Delphi. Наверное, я тоже в душе кулхацкер :D
>>> Но на этот случай можно написать в одну строку
Дело не в количестве строк, а в количестве операторов ;-) Ну, не люблю я еще со времен школьной математики прописывать все промежуточные действия, если и без них все понятно. Грубо говоря, можно записать и так:
function CalcHypotenuse(Cathetus1,Cathetus2 : Extended) : Extended;
var
A,B : Extended;
begin
A:=Sqr(Cathetus1);
B:=Sqr(Cathetus2);
Result:=A+B;
Result:=Sqrt(Result);
end;
Или по Вашему варианту для экономии строк так:
function CalcHypotenuse(Cathetus1,Cathetus2 : Extended) : Extended;
var
A,B : Extended;
begin
A:=Sqr(Cathetus1); B:=Sqr(Cathetus2); Result:=A+B; Result:=Sqrt(Result);
end;
Но я, наверное, все же написал бы так:
function CalcHypotenuse(Cathetus1,Cathetus2 : Extended) : Extended;
begin
Result:=Sqrt(Sqr(Cathetus1)+Sqr(Cathetus2));
end;
№ 673 20-05-2009 03:01 | |
Ответ на »сообщение 670« (Geo)
___________________________
Поэтому я не считаю зазорным для той же GetMem при необходимости дописать собственную оболочку Чем Вам New не нравится, только невозможностью что-то присвоить сразу после выделения памяти? Такая экономность в количестве строчек кода характерна для C-шников. Но на этот случай можно написать в одну строку: New(P); P^ := 10; :o)
Если серьёзно, то пример довольно искусственный, ни кто не будет выделять память только под одну переменную Integer, чаще всего выделяют память под более сложные структуры, в которых простым присваиванием := не обойтись. Во всяком случае в исходниках от Delphi5 я нашел только 3 места, где результату функции чтото присваивается, а операторов Goto два.
P.S. чтобы избежать дальнейших обвинений в мелких придирках и занудстве, скажу, что я в принципе не против холодильника в спальне, но сам бы его туда не поставил...
№ 672 20-05-2009 02:15 | |
Ответ на »сообщение 671« (Антон Григорьев)
___________________________
Да, именно так. Я этот момент помню, только притормозил при написании. Собственно, поэтому я и не стал по памяти прописывать реализацию метода, возвращающего указатель на нужную область памяти, а также инициализацию класса, где я получаю указатель на начало данных ;-)
№ 671 20-05-2009 01:57 | |
Ответ на »сообщение 669« (Geo)
___________________________
указатель. полученный через ScanLine[0], является указателем на начало этой области, заполненной триплетами RGB.
Нет, не так. У BMP строки изображения идут в порядке "снизу вверх", поэтому указатель на начало всей области - это Bitmap.ScanLine[Bitmap.Height-1]
№ 670 20-05-2009 01:51 | |
Елы-палы! Напортачил все же в спешке. Естественно, что тип TRGBColor определяется так:
type
TRGBColor = packed record
R,G,B : Byte;
end;
;-)
Ответ на »сообщение 664« (Cepгей Poщин)
___________________________
>>> Возможно по этой причине GetMem не функция а процедура, чтобы не было соблазна писать
А вот здесь есть один нюанс. Очень удобно использовать именно вункции, так как их можно встраивать в выражения без предварительного оператора присваивания для сохранения в переменной результата. А это приводит к более компактной записи. Но иногда нужно и результат сохранить и в выражение хочется встроить. С Си для этого есть особенности синтаксиса, а в Паскале, увы, нет. Поэтому я не считаю зазорным для той же GetMem при необходимости дописать собственную оболочку:
function MyGetMem(var P : PInteger) : PInteger;
begin
GetMem(Result,SizeOf(Integer);
end;
И тогда мы можем со спокойной совестью писать вот так:
var
P : PInteger;
begin
MyGetMem(P)^=10;
вместо развесистого
var
P : PInteger;
begin
GetMem(P,SizeOf(Integer));
P^:=10;
№ 669 20-05-2009 01:37 | |
Ответ на »сообщение 667« (Cepгей Poщин)
___________________________
>>> Если Вы всёравно делали обёртку в виде своего класса, то можно было бы сделать методы Set и Get, которые бы работали со значением, а не с указателем
"Ой, дяденька, какой ты ну-у-у-дный"
Ясно дело, так оно и было. Я воспользовался тем, что для DIB все данные хранятся в памяти в одной области. Соответственно, указатель. полученный через ScanLine[0], является указателем на начало этой области, заполненной триплетами RGB. Естественно, я сделал классовую обертку и свойство с методами Set и Get. Примерно слелдующим образом:
type
TRGBColor = packed record
B,G,R : Byte;
end;
PRGBColor = ^TRGBColor;
TMap = class
private
function GetColorPtr(X,Y : Integer) : PRGBColor;
function GetColor(X,Y : Integer) : TRGBColor;
procedure SetColor(X,Y : Integer; Val : TRGBColor);
public
property Color[C,Y : Integer] : TRGBColor read GetColor write SetColor;
end;
function TMap.GetColorPtr(X,Y : Integer) : PRGBColor;
begin
end;
function TMap.GetColor(X,Y : Integer) : TRGBColor;
begin
Result:=GetColorPtr(X,Y)^;
end;
procedure TMap.SetColor(X,Y : Integer; Val : TRGBColor);
begin
GetColorPtr(X,Y)^:=Val;
end;
Именно обертка. Но я обломился вычислять адрес два раза (в методе Get и в методе Set) и поэтому вынес его вычисление в отдельный метод -- GetColorPtr. К тому же, если бы я что-то напортачил в вычислнении адреса, переписывать пришлось бы только один метод, а не два. Собственно, я и напортачил: забыл, что для каждой сканлинии начало выровнено на 4 байта, соответственно, если ширина картинки не кратна четырем, то в конце каждой сканлинии будет несколько лишних байт для заполнения остатка. Но благодаря своей предусмотрительности быстренько все поправил.
Код пишу по памяти, и мог что-то напортачить, но, думаю, смысл понятен. Указатель на ScanLine[0] я получаю при инициализации и сохраняю в private-поле (просто не стал прописывать всю реализацию класса). Никакую память я сам внутри класса не выделяю и не освобождаю.
№ 668 20-05-2009 01:25 | |
Ответ на »сообщение 667« (Cepгей Poщин)
___________________________
TMemoryStream содержит размер и больше чем он может дать он не даст и не примит, а через Pointer можно что угодно записать с риском испортить содержимое памяти без сообщений об ошибке. Ну и опять же в большом проекте, кто его там разберет, надо, или не надо освобождать память...
Это уже мелкие придирки.
Метод может, например, возвращать PInteger со всеми необходимыми проверками. С освобождением памяти вопрос тоже решаемый - даже в WinAPI есть разные варианты освобождения памяти. И ничего, живем как-то, применяем.
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|