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 недоступны.
|
|
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
|
Указатели и выделение памяти
Я использую только для классов и строк. И вообще, думаю, что чем меньше память дрочить, тем лучше и система, и прога работать будет
Константы
Самый главный их плюс (я уже говорил) нахождение ошибок еще на стадии компиляции. И для этого не жалко даже памяти, если она конечно выделяться все-таки будет. Если ты вдруг (случайно) ошибся, перепутал и начал активно юзать константу в присвоениях, то ошибку получишь еще ДО дебаггинга
|
|
Asher |
Отправлено: 22.04.2005, 08:29 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
QUOTE | Если ты вдруг (случайно) ошибся, перепутал и начал активно юзать константу в присвоениях, то ошибку получишь еще ДО дебаггинга |
С костантами описанными в define, в принципе, будет то-же самое.
Компилятор выругается что в этом месте выражения требуется lvalue.
QUOTE | Не факт, что каждый компилер справится со взаимозаменяемостью const и define. |
Я имел ввиду не это. Я хотел сказать, что в тех случаях определения констант, где можно применить define (а его область применения все-же уже чем у const) память выделяться не будет. В пользу применения const в этих случаях говорит унификация.
Константы массивы, константные значения параметров функций, и .т.д. и почему тогда некоторые из констант должны быть описаны define?
QUOTE | Кстати, занести вычисляемое значение в const переменную??? |
Простейший случай:
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 помещать нельзя.
|
|
vvoid |
Отправлено: 22.04.2005, 17:31 |
|
Машинист паровоза
Группа: Участник
Сообщений: 171
|
Извиняюсь, но куда помещать нельзя?
|
|
Георгий |
Отправлено: 22.04.2005, 23:06 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
т.н. "умные" указатели, в BCB класс называется auto_ptr
умеют сами обрабатывать выход указателя из области видимости и уничтожения объекта указатель на который, был "потерян"
PS. вы не поверите, но за последние 2 года указателями пользовался всего 2 или 3 раза да и то только в специальных целях — погоня за скоростью (разы, а не проценты) и работа с данными из обработчика прерывания (временные данные не мог разместить в стеке). А во всех остальных случаях указатели были от меня спрятаны за ссылками и STL containers и никакого дискомфорта
Отредактировано Георгий — 22/04/2005, 23:12 |
|
Treumer |
Отправлено: 25.04.2005, 10:11 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 92
|
QUOTE (Георгий @ 22/04/2005, 23:06) | PS. вы не поверите, но за последние 2 года указателями пользовался всего 2 или 3 раза да и то только в специальных целях — погоня за скоростью (разы, а не проценты) и работа с данными из обработчика прерывания (временные данные не мог разместить в стеке). А во всех остальных случаях указатели были от меня спрятаны за ссылками и STL containers и никакого дискомфорта |
Вообще-то, за стеком надо следить еще более аккуратно, чем за указателями.
Искусственное переполнение стека — любимый прием взлома удаленных компьютеров хакерами.
Хотя, если это просто бухгалтерская программка — боятиься — конечно — нечего. |
|
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 | переменная удаляется, но указатель остаётся... |
Вы уверенны ? Об этом где-то написано ? Скажите где пожалуйста, я просто не встречал и раньше не слышал
|
|
Treumer |
Отправлено: 25.04.2005, 14:16 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 92
|
QUOTE (Sl@Sh @ 25/04/2005, 14:07) | QUOTE | переменная удаляется, но указатель остаётся... |
Вы уверенны ? Об этом где-то написано ? Скажите где пожалуйста, я просто не встречал и раньше не слышал |
А что тут удивительного ?
Может — конечно, компилятор и сделает оптимизацию — уберет переменную-указатель из стека, как только будет сделан delete, но вообще-то — он не обязан
Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет.
Отредактировано Treumer — 25/04/2005, 14:16 |
|
Sl@Sh |
Отправлено: 25.04.2005, 14:19 |
|
Мастер участка
Группа: Участник
Сообщений: 383
|
Для меня это не удивительно. Я просто первый раз слышу т.к. маловато знаю, вот поэтому и вопрос об источнике задал.
QUOTE | Но вообще указатели на простые типы — в C++ — на мой взгляд — лишь рудимент из чистого С и использовать их смысла никакого нет. |
Если не считать, что сам билдер их использует очень часто
|
|
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 — Вы обращались ко мне, а значит всё нормально т.к. всё что вы написали для меня очень полезно.
Спасибо !
|
|
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;
|
Указатель на некий массив байтов. А когда работаешь с криптой лучше всего самому контролировать доступ, модификацию, удаление твоих данных! Не говоря уже про критичные по скорости участки! |
Вообще говоря — массив значенией — это уже не простой тип данных.
Естественно, что указатели на сложные структуры, массивы и классы как таковые — основа С++. Это же не Ява.
Только пользуясь ими можно решать серьезные задачи — когда данных много, а ресурсы ограничены.
Но в том то и "оборотная сторона медали" С и С++ — пользуясь ими надо быть осторожным — легко допустить ошибку приводящую к "утечке памяти" или нестабильности работы программы.
Такие ошибки трудно ловить и проявляются они обычно не на тестовых, а на реальных данных — что всегда приводит к большим проблемам.
Поэтому-то в Яве и исключили возможность работы с указателями напрямую- чтобы даже начинающий не мог "наворотить делов"
Тем самым, правда, серьезно ограничив возможности разработчика, особенно в оптимизации скорости работы программы.
А начинающим — действительно — лучше использовать — когда возможно — auto_ptr — он во многих случаях спасает от ошибок по "забывчивости"
Отредактировано Treumer — 25/04/2005, 17:49 |
|
vvoid |
Отправлено: 25.04.2005, 18:03 |
|
Машинист паровоза
Группа: Участник
Сообщений: 171
|
Кто-нибудь толком мне расскажет, что же такое этот auto_ptr?
2Treumer>
Извиняюсь, не заметил словосочетание простые типы. Наверное было бы слишком муторно разрешать деалать указатели на одни типы данных и запрещать на другие!
А по поводу указателей в Jave, я всё таки придерживаюсь мнения, что их исключили из-за ориентации Javы на программирование для интернета. Представьте, чтобы смог сделать "плохой дядя-программист" имея он возможность напрямую работать с памятью в апплете, который тихо-мирно загружается в вашем броузере! (Положить броузер — как минимум и без особых напрягов)
|
|
Treumer |
Отправлено: 25.04.2005, 18:45 |
|
Станционный диспетчер
Группа: Участник
Сообщений: 92
|
QUOTE (vvoid @ 25/04/2005, 18:03) | Кто-нибудь толком мне расскажет, что же такое этот auto_ptr?
2Treumer>
Извиняюсь, не заметил словосочетание простые типы. Наверное было бы слишком муторно разрешать деалать указатели на одни типы данных и запрещать на другие!
А по поводу указателей в Jave, я всё таки придерживаюсь мнения, что их исключили из-за ориентации Javы на программирование для интернета. Представьте, чтобы смог сделать "плохой дядя-программист" имея он возможность напрямую работать с памятью в апплете, который тихо-мирно загружается в вашем броузере! (Положить броузер — как минимум и без особых напрягов) |
Если бы в С++ изменили работу указателей, было бы невозможно портировать или использовать имеющийся код на С в программах на С++.
Это было бы, конечно, весьма неразумно.
Но начинающий С++ программист вполне может не использовать указателей на простые типы, ведь в С++ есть возможность передачи по ссылке.
На счет Явы — может так оно и было, но Микрософт -как всегда — все испортил сделав технологию 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-х Гигов на задачу по любому не отдаст.
|
|
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 могу запросить. |
|