C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

стр.: (3) < 1 [2] 3 >
Оценивание качества кода
vvoid
Отправлено: 21.04.2005, 15:52


Машинист паровоза

Группа: Участник
Сообщений: 171



FataLL:
QUOTE
Все-таки сделал бы const int вместо #define и еще не нравятся мне эти подчеркивания... Хотя мне и TForm1 не нравится

Полностью согласен с подчёркиваниями — они делают код какимто уж очень широким и размазанным, а разные слова в названии переменной )(функции, класс, ...) всегда можно выделить используя заглавные буквы.
TForm1 — Разумеется тоже не нормальное название — ровным счётом ничего не говорит про саму форму!
А вот на счёт const int вместо #define — не факт. Зачем мне постоянно хранить в сегменте данных некую переменную? #define для числовых констант — самое оно!
vvoid
Отправлено: 21.04.2005, 15:57


Машинист паровоза

Группа: Участник
Сообщений: 171



А по поводу передачи в функцию параметров по ссылке оталкиваюсь от таких соображений:
- тип параметра и соответственно его размер;
- необходимость изменять внешнее значение этого параметра в функции (в данном случае первый пункт не отменяется, поскольку иногда лучше использовать указатель, а не ссылку)
Asher
Отправлено: 21.04.2005, 16:44


Мастер участка

Группа: Модератор
Сообщений: 550



QUOTE
А вот на счёт const int вместо #define — не факт. Зачем мне постоянно хранить в сегменте данных некую переменную?

В тех случаях, где const взаимозаменяемо с define память под константу скорей всего выделятся не будет.
Дополнительно к этому в const можно поместить вычисляемое на этапе компиляции значение, что с define не пройдет.
Память гарантированно выделится только при массиве констант, в случае невозможности получить значение на этапе компиляции или при доступе к константе по адресу.

Но и эти варианты использования define недоступны. biggrin.gif
Guest
Отправлено: 21.04.2005, 18:01


Не зарегистрирован







QUOTE (Asher @ 18/04/2005, 10:48)
QUOTE
Только первый вариант и есть "грамотный",
а второй — просто — распространенный

То не все так очевидно, с выбором "грамотности" вариантов.
Расширяя пример как
1) void Func(const T &a);
2) void Func(T a);
можно заметить, что T-может иметь размер и меньше размера ссылки, что может быть существенно, например при глубокой рекурсии, а во вторых в многопоточном приложении, я лично, предпочел бы поработать с один раз сделанной копией значения, чем непосредственно несколько раз обращаться к этому значению в функции.

Тогда грамотно будет так:
2) void Func(const T a);

В общем случае — const — обязателен для неизменяемых значений.
От него хуже не будет.
Sl@Sh
Отправлено: 21.04.2005, 18:43


Мастер участка

Группа: Участник
Сообщений: 383



Во многих книгах рекомендуют вместо директивы #define использовать const.

Кстати, а кому нравиться с указателями работать ? Ну например так :
CODE

int *a = new int;
//....
delete *a;


Поидее переменная удаляется, но её использование не очень красиво выглядит. Думаю тут многие согласятся.
vvoid
Отправлено: 21.04.2005, 19:10


Машинист паровоза

Группа: Участник
Сообщений: 171



Asher
QUOTE
В тех случаях, где const взаимозаменяемо с define память под константу скорей всего выделятся не будет.
Дополнительно к этому в const можно поместить вычисляемое на этапе компиляции значение, что с define не пройдет.


Не факт, что каждый компилер справится со взаимозаменяемостью const и define. (в билдере, по-моему, для этого специальная "галочка" в свойствах есть).
В #define помещаются только предопределённые константы, то есть речь само собой не идёт о том, чтобы считать её значение в ходе выполнения. Получается, что когда смотришь на код, ты точно знаешь, что эта штука у тебя нигде по ходу программы не поменяется.

PS* Кстати, занести вычисляемое значение в const переменную??? Это означает, что эта переменная является локальной, для определённого логического блока (функции, например). А область действия некой предопределённой константы зачастую больше. У меня по крайней мере. :-)
FataLL
Отправлено: 22.04.2005, 01:17


Дежурный стрелочник

Группа: Участник
Сообщений: 37



Указатели и выделение памяти
Я использую только для классов и строк. И вообще, думаю, что чем меньше память дрочить, тем лучше и система, и прога работать будет

Константы
Самый главный их плюс (я уже говорил) нахождение ошибок еще на стадии компиляции. И для этого не жалко даже памяти, если она конечно выделяться все-таки будет. Если ты вдруг (случайно) ошибся, перепутал и начал активно юзать константу в присвоениях, то ошибку получишь еще ДО дебаггинга smile.gif
Asher
Отправлено: 22.04.2005, 08:29


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
QUOTE
Если ты вдруг (случайно) ошибся, перепутал и начал активно юзать константу в присвоениях, то ошибку получишь еще ДО дебаггинга

С костантами описанными в define, в принципе, будет то-же самое.
Компилятор выругается что в этом месте выражения требуется lvalue.

QUOTE
Не факт, что каждый компилер справится со взаимозаменяемостью const и define.

Я имел ввиду не это. Я хотел сказать, что в тех случаях определения констант, где можно применить define (а его область применения все-же уже чем у const) память выделяться не будет. В пользу применения const в этих случаях говорит унификация. biggrin.gif
Константы массивы, константные значения параметров функций, и .т.д. и почему тогда некоторые из констант должны быть описаны define?

QUOTE
Кстати, занести вычисляемое значение в const переменную???

Простейший случай: biggrin.gif
CODE

const int c_siError1 = 0;
const int c_siError2 = c_siError1 + 1;


P.S. Надо мне учиться выражаться яснее сразу, а то как в анекдоте времен Рейгана.
"15 минут выступал президент и два часа после него советник, объясняя народу что президент хотел сказать этой речью."
vvoid
Отправлено: 22.04.2005, 15:19


Машинист паровоза

Группа: Участник
Сообщений: 171



Asher>
QUOTE
Константы массивы, константные значения параметров функций, и .т.д. и почему тогда некоторые из констант должны быть описаны define?


В том то и дело, что область применения #define уже!!! Согласись, что число Пи это не константное значение параметра функции! И по этому, когда я вижу в коде #define — понимаю, что это значение уже никогда не изменится, на него нельзя пытаться получить указатель и т.д.

2FataLL>
Да и если ты попытаешься задефайненой константе что-нить присвоить, но компилеру это не понравится ещё больше, чем присваивание значения некой const переменной!
vvoid
Отправлено: 22.04.2005, 16:18


Машинист паровоза

Группа: Участник
Сообщений: 171



По поводу указателей. Мне лично нравится их использовать! Иногда случаются ситуации, когда тебе надо знать, что происхоит с твоими данными, а лучший способ — обрабатывать их самому! (Java мне как раз и невзлюбилась, из-за отсутствия указателей. Хотя создатетей можно понять — дай плохому программеру (нехорошему дяде) использовать в web applet-ах указатели, и пользователи больше никогда не будут заходить в инет — не смогут ;-) )

Я думаю Sl@sh, чуток напутал с кодом (поставил лишнюю муху после delete).

А вообще, я даже при создании указателя на один int (как в примере)использую нечно вроде:

CODE

int *ValuePtr;

ValuePtr = new int [1];
......
delete[] ValuePtr;


Кто знает, подскажите, может так делать нехорошо?
Asher
Отправлено: 22.04.2005, 17:08


Мастер участка

Группа: Модератор
Сообщений: 550



QUOTE
то знает, подскажите, может так делать нехорошо?

Конечно нехорошо.
Такие указатели, на массивы, в auto_ptr помещать нельзя. biggrin.gif
vvoid
Отправлено: 22.04.2005, 17:31


Машинист паровоза

Группа: Участник
Сообщений: 171



Извиняюсь, но куда помещать нельзя?
Георгий
Отправлено: 22.04.2005, 23:06


Почетный железнодорожник

Группа: Модератор
Сообщений: 874



т.н. "умные" указатели, в BCB класс называется auto_ptr
умеют сами обрабатывать выход указателя из области видимости и уничтожения объекта указатель на который, был "потерян"

PS. вы не поверите, но за последние 2 года указателями пользовался всего 2 или 3 раза да и то только в специальных целях — погоня за скоростью (разы, а не проценты) и работа с данными из обработчика прерывания (временные данные не мог разместить в стеке). А во всех остальных случаях указатели были от меня спрятаны за ссылками и STL containers и никакого дискомфорта smile.gif

Отредактировано Георгий — 22/04/2005, 23:12
Treumer
Отправлено: 25.04.2005, 10:11


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (Георгий @ 22/04/2005, 23:06)
PS. вы не поверите, но за последние 2 года указателями пользовался всего 2 или 3 раза да и то только в специальных целях — погоня за скоростью (разы, а не проценты) и работа с данными из обработчика прерывания (временные данные не мог разместить в стеке). А во всех остальных случаях указатели были от меня спрятаны за ссылками и STL containers и никакого дискомфорта smile.gif

Вообще-то, за стеком надо следить еще более аккуратно, чем за указателями.
Искусственное переполнение стека — любимый прием взлома удаленных компьютеров хакерами.

Хотя, если это просто бухгалтерская программка — боятиься — конечно — нечего. biggrin.gif
Konstantine
Отправлено: 25.04.2005, 10:22


Мастер участка

Группа: Модератор
Сообщений: 545



QUOTE (Sl@Sh @ 21/04/2005, 18:43)
Кстати, а кому нравиться с указателями работать ? Ну например так :
CODE

int *a = new int;
//....
delete *a;


Поидее переменная удаляется, но её использование не очень красиво выглядит. Думаю тут многие согласятся.

переменная удаляется, но указатель остаётся... а в данном случае указатель занимает места столько же, сколько и переменная...

З.Ы.: зачем платить дважды?
Sl@Sh
Отправлено: 25.04.2005, 14:07


Мастер участка

Группа: Участник
Сообщений: 383



QUOTE
переменная удаляется, но указатель остаётся...


Вы уверенны ? Об этом где-то написано ? Скажите где пожалуйста, я просто не встречал и раньше не слышал sad.gif
Treumer
Отправлено: 25.04.2005, 14:16


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (Sl@Sh @ 25/04/2005, 14:07)
QUOTE
переменная удаляется, но указатель остаётся...


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

А что тут удивительного ?
Может — конечно, компилятор и сделает оптимизацию — уберет переменную-указатель из стека, как только будет сделан delete, но вообще-то — он не обязан wink.gif

Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.

Отредактировано Treumer — 25/04/2005, 14:16
Sl@Sh
Отправлено: 25.04.2005, 14:19


Мастер участка

Группа: Участник
Сообщений: 383



Для меня это не удивительно. Я просто первый раз слышу т.к. маловато знаю, вот поэтому и вопрос об источнике задал.

QUOTE
Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.


Если не считать, что сам билдер их использует очень часто smile.gif
vvoid
Отправлено: 25.04.2005, 15:27


Машинист паровоза

Группа: Участник
Сообщений: 171



QUOTE (Treumer @ 25/04/2005, 14:16)
Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.

По-моему смысл есть!!!

CODE

unsigned char   *ByteArrayPtr;


Указатель на некий массив байтов. А когда работаешь с криптой лучше всего самому контролировать доступ, модификацию, удаление твоих данных! Не говоря уже про критичные по скорости участки!
vvoid
Отправлено: 25.04.2005, 15:28


Машинист паровоза

Группа: Участник
Сообщений: 171



2Sl@sh>
Указатель — такая же самая переменная как и int, то есть занимает определённое место в памяти, размером такое же, как и разрядность проца — драугих вариантов не встречал, да вообще они возможны? (Кстати тип int, тоже изначально был задуман, как тип, с которым процу будет легче всего общаться, из-за того, что его размер и разрядность проца одинаковые, как это с 64-битными процами, кто-нить знает?). Так вот, когда ты пишешь
CODE

SomeType   *SomeTypePtr;

в памяти создаётся некий участок, в который потом будет записан некий реальный адрес (сначала там всякая байда).
Далее, ты делаешь:
CODE

SomeTypePtr = new SomeType;
или
SomeTypePtr = new SomeType[Count];

В куче (некая область памяти) выделяется кусок памяти размером sizeof(SomeType) или sizeof(SomeType * Count) — для второго случая, и этот кусок памяти какм-то образом помечается как уже используемый, а в твой указатель SomeTypePtr заносится адрес начала того самого выделенного из кучи куска памяти.
И наконец:
CODE

delete SomeTypePtr;
или
delete[] SomeTypePtr;

Эти команды помечают выделенную в куче область, как неиспользованную. Заметь, сам указатель SomeTypePtr, как был, так и остался! То есть ты спокойно можешь снова писать SomeTypePtr = new SomeType; ... и т.д.

PS* если всё слишком подробно, не обижайтесь — никого не хочу обидеть — просто выложил как знаю (авось кому-то поможет подружиться с указателями). А если что не так — поправьте, буду признателен
Sl@Sh
Отправлено: 25.04.2005, 16:01


Мастер участка

Группа: Участник
Сообщений: 383



QUOTE
PS* если всё слишком подробно, не обижайтесь — никого не хочу обидеть — просто выложил как знаю (авось кому-то поможет подружиться с указателями). А если что не так — поправьте, буду признателен


to vvoid — Вы обращались ко мне, а значит всё нормально т.к. всё что вы написали для меня очень полезно. smile.gif

Спасибо ! smile.gif
Treumer
Отправлено: 25.04.2005, 17:38


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (vvoid @ 25/04/2005, 15:27)
QUOTE (Treumer @ 25/04/2005, 14:16)
Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.

По-моему смысл есть!!!

CODE

unsigned char *ByteArrayPtr;


Указатель на некий массив байтов. А когда работаешь с криптой лучше всего самому контролировать доступ, модификацию, удаление твоих данных! Не говоря уже про критичные по скорости участки!

Вообще говоря — массив значенией — это уже не простой тип данных. biggrin.gif
Естественно, что указатели на сложные структуры, массивы и классы как таковые — основа С++. Это же не Ява. biggrin.gif
Только пользуясь ими можно решать серьезные задачи — когда данных много, а ресурсы ограничены.

Но в том то и "оборотная сторона медали" С и С++ — пользуясь ими надо быть осторожным — легко допустить ошибку приводящую к "утечке памяти" или нестабильности работы программы.
Такие ошибки трудно ловить и проявляются они обычно не на тестовых, а на реальных данных — что всегда приводит к большим проблемам.
Поэтому-то в Яве и исключили возможность работы с указателями напрямую- чтобы даже начинающий не мог "наворотить делов" smile.gif
Тем самым, правда, серьезно ограничив возможности разработчика, особенно в оптимизации скорости работы программы.

А начинающим — действительно — лучше использовать — когда возможно — auto_ptr — он во многих случаях спасает от ошибок по "забывчивости" wink.gif

Отредактировано Treumer — 25/04/2005, 17:49
vvoid
Отправлено: 25.04.2005, 18:03


Машинист паровоза

Группа: Участник
Сообщений: 171



Кто-нибудь толком мне расскажет, что же такое этот auto_ptr?
2Treumer>
Извиняюсь, не заметил словосочетание простые типы. Наверное было бы слишком муторно разрешать деалать указатели на одни типы данных и запрещать на другие!
А по поводу указателей в Jave, я всё таки придерживаюсь мнения, что их исключили из-за ориентации Javы на программирование для интернета. Представьте, чтобы смог сделать "плохой дядя-программист" имея он возможность напрямую работать с памятью в апплете, который тихо-мирно загружается в вашем броузере! (Положить броузер — как минимум и без особых напрягов) biggrin.gif
Treumer
Отправлено: 25.04.2005, 18:45


Станционный диспетчер

Группа: Участник
Сообщений: 92



QUOTE (vvoid @ 25/04/2005, 18:03)
Кто-нибудь толком мне расскажет, что же такое этот auto_ptr?
2Treumer>
Извиняюсь, не заметил словосочетание простые типы. Наверное было бы слишком муторно разрешать деалать указатели на одни типы данных и запрещать на другие!
А по поводу указателей в Jave, я всё таки придерживаюсь мнения, что их исключили из-за ориентации Javы на программирование для интернета. Представьте, чтобы смог сделать "плохой дядя-программист" имея он возможность напрямую работать с памятью в апплете, который тихо-мирно загружается в вашем броузере! (Положить броузер — как минимум и без особых напрягов) biggrin.gif

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

Но начинающий С++ программист вполне может не использовать указателей на простые типы, ведь в С++ есть возможность передачи по ссылке.

На счет Явы — может так оно и было, но Микрософт -как всегда — все испортил сделав технологию ActiveX — позволющую делать все что захочешь, и потому ставшую может даже более популярной, чем ява-аплеты.

Читай про auto_ptr тут:
http://trubetskoy1.narod.ru/principleres.html
vitavita
Отправлено: 25.04.2005, 18:56


Дежурный стрелочник

Группа: Участник
Сообщений: 59



QUOTE
их исключили из-за ориентации Javы на программирование для интернета.

Именно из-за этого. И в С# тоже
QUOTE
Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.

Мне приходится использовать указатели. пример:
QUOTE
class Vox
{private: // User declarations
unsigned char *V;

public: // User declarations
Vox(int,int,int);
}
Vox::Vox(int i,int j , int k ){//возможные значения i=j=k= 1000;
int Count= i*j*k;
unsigned char *V=new unsigned char [Count];
}

Т. е. памяти надо за 1 Gb
Вы скажете что можно использовать
vector< vector< vector< unsigned char>>> V (i, vector< vector< unsigned char>>(j,vector< unsigned char>(k)) ?

И у меня вопрос зачем использовать delete[] V; если результат будет такой же как и delete V; ( по крайне мере в Builder) ? Знаю — Страуструп пишет что надо delete[] ,но разницы не понял , т.к. проверял- освобождают память одинаково.

Отредактировано vitavita — 25/04/2005, 18:58
vvoid
Отправлено: 25.04.2005, 19:27


Машинист паровоза

Группа: Участник
Сообщений: 171



О. Вот можно и код оценить! (тему помните???)
CODE

class Vox
{private: // User declarations
unsigned char *V;

public:  // User declarations
     Vox(int,int,int);
}
Vox::Vox(int i,int j , int k ){//возможные значения i=j=k= 1000;
int Count= i*j*k;
unsigned char *V=new unsigned char [Count];
}


Скажу чесно и не в обиду, разобраться можно, только в силу простоты выполняемых действий!

Кстати Гигабайт памяти всегда получается нормально выделить, ведь на 32-разрядном компе максимум 4 294 967 296 байта? ... а может я и ошибаюсь.


2Treumer>
Спасибо за ссылку

2vitavita>

QUOTE

И у меня вопрос зачем использовать delete[] V; если результат будет такой же как и delete V; ( по крайне мере в Builder) ?


Знаешь, иногда даже память, выделенную по malloc можно освободить delete-ом, но совершенно НЕ ГАРАНТИРУЕТСЯ корректное поведение, и если пытаешься писать стабильные программы, то уж следуй указаниям создателей (к Microsoft — не относится :-)).
Вот так и delete с delete[]. Кстати Visual, если применить delete вместо delete[] — свалится :-). А по поводу разницы, могу задать встречый вопрос, почему в семействе new ... delete, нет аналога realloc из malloc ... realloc ... free.
Рассказывали мне, что знающие ребята проверяли, действительно нельзя было сделать такой аналог при новой идеологии (ведь не зря же вообще придумали этот new).
Остаётся верить "Мёртвому" (Страуструп) на слово!

Кстати, а как осуществлялась проверка, что память действительно освобождается?

Отредактировано vvoid — 25/04/2005, 19:33
vitavita
Отправлено: 25.04.2005, 20:02


Дежурный стрелочник

Группа: Участник
Сообщений: 59



QUOTE
Кстати, а как осуществлялась проверка, что память действительно освобождается?
Кстати Гигабайт памяти всегда получается нормально выделить

Проверка осуществлялась просто просмотром свободной оперативной памяти. При таких объемах , на пределе , сразу видно.
Не знаю , но на обычных компах оперативной больше 1,5- 2 Gb не бывает
В С# delete[] специально убрали т.к. компилятор же знает что он удаляет.
Asher
Отправлено: 25.04.2005, 20:22


Мастер участка

Группа: Модератор
Сообщений: 550



QUOTE
И у меня вопрос зачем использовать delete[] V; если результат будет такой же как и delete V; ( по крайне мере в Builder) ?

Всегда есть накладные расходы, хотя бы для хранения размера массива.
CODE
MyStruct* pStruct = new MyStruct[n];
delete [] pStruct;//освобождает n*sizeof(pStruct) + накладные.

n оператор delete[]() выковыривает из этих самых накладных расходов.
В VC он хранится сразу перед указателем на массив.
То, что Builder сам приглядывает за пользователем ничего плохого нет, но это не повод писать неправильно (не по стандарту)

P.S. Windows больше 2-х Гигов на задачу по любому не отдаст. biggrin.gif
vvoid
Отправлено: 25.04.2005, 20:28


Машинист паровоза

Группа: Участник
Сообщений: 171



QUOTE
Не знаю , но на обычных компах оперативной больше 1,5- 2 Gb не бывает

Тут дело идёт не про оперативную память, а про виртуальную, а её можно дать больше. ;-)
2Asher>
А 2 гига из 4-х возможных винда себе забирает. Ты это имеешь ввиду?

Отредактировано vvoid — 25/04/2005, 20:31
vitavita
Отправлено: 25.04.2005, 21:54


Дежурный стрелочник

Группа: Участник
Сообщений: 59



QUOTE
Тут дело идёт не про оперативную память, а про виртуальную, а её можно дать больше.

А эта мне и даром не нужна — мне нужно считать а не мучаться
QUOTE
Windows больше 2-х Гигов на задачу по любому не отдаст

А что это действительно так . А где это написано ? Я не проверял . А то заставлю начальника ракошелиться а потом выяснится , что нельзя . А я потенциально и 4Gb могу запросить.
стр.: (3) < 1 [2] 3 >
Вернуться в Вопросы программирования в C++Builder