![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
bern |
|
|||
Unregistered |
Здраствуйте! У меня к вам такая просьба - объясните мне пожалуйста чем таким кардинальным отличается динамическая память от массивов и что можно сделать с помощью new&delete чего нельзя было бы сделать с помощью массивов? Ведь в динамической памяти точно также выделяется место под отдельные переменные и массивы, так в чём разница ? И вообще почему этот метод называется динамическим?
|
|||
|
||||
blackofe |
|
|||
![]() Бывалый ![]() Профиль Группа: Участник Сообщений: 173 Регистрация: 29.11.2005 Репутация: 4 Всего: 4 |
в c++ массивы должны иметь константную размерность. динамическое выделение памяти позволяет объявить массив произвольного размера (который, вообще говоря, не известен на этапе компиляции). |
|||
|
||||
Dray |
|
||||||||||
![]() Материалист ![]() ![]() Профиль Группа: Участник Сообщений: 652 Регистрация: 7.10.2003 Где: г. Всеволожск Репутация: 2 Всего: 6 |
Если делаешь так:
То а создается в стеке. Если так:
То а создается в куче. Разница в том, что переполнение стека куда реальнее чем переполнение кучи. Вообще указатели и динамическое распределение памяти чаще используются для структур данных самодельных например в списках:
Если интересно про списки то лучше воспользоваться поиском. Это уже обсуждалось. Динамической она называется поскольку количество требуемой памяти определяется во время выполнения программы. Например при создании масива так:
Нужно заранее знать кол-во элементов массива. И использовать только константу. А если так:
Не обязательно знать колличество элементов заранее можно ввести прям с клавиатуры. Память распределяется динамически. |
||||||||||
|
|||||||||||
Aleksandor |
|
|||
![]() Практик ![]() ![]() Профиль Группа: Участник Сообщений: 272 Регистрация: 22.11.2005 Где: россия, зеленогра д Репутация: 0 Всего: 12 |
Динамический способ рулит потому что-
а) экономит память (и за счет этого повышает быстродействие программы). Часто это вообще критично для программы. б) не загромождает стек - массив (статический) как любая другая переменная передается в стеке и если он велик то произойдет переполнение стека отведенного потоку и приложение рухнет ![]() часто мы не знаем сколько элементов будет в массиве и соответственно сколько памяти потребуется, поэтому лучше выделять память динамически, по мере роста массива. new только один из способов, в Win API используем HeapAlloc и VirtualAlloc Пример недостатки статического выделения памяти- char array[1000][1000]; // массив 1000 строк по 1000 байт каждая - если массив не в глобальной памяти, то он вызовет переполнение стека - каждая строка может содержать всего 1 символ (+нулевой байт), итого 2 байта. остальные 998000 байт расходуются впустую - длина строки может превысить 1000 байт, тогда мы не сможем впихнуть ее в массив - мы можем не знать заранее сколько строк потребуется, может всего одна, а может 1001, в первом случае мы зря расходуем до 999998 байт, во втором вообще труба. Нельзя всунуть больше 1000 строк в этот массив! Динамическое выделение памяти снимает все эти проблемы ![]() Это сообщение отредактировал(а) Aleksandor - 3.12.2005, 11:01 -------------------- Call out Gouranga be happy!!! Gouranga Gouranga Gouranga .... That which brings the highest happiness!! |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
ну и контроль времени жизни еще можно упомянуть
с точки зрения памяти время жизни - время, когда объект занимает память в случае использования стека время жизни контролируется тем, когда выполнение входит в блок, в котором объявлен объект, и тем, когда выходит в случае с динамическим распределением можно удалять объект раньше или позже в зависимости от, например, булевой переменной... -------------------- qqq |
|||
|
||||
Guest |
|
|||
Unregistered |
Спасибо за отеты.Можно ещё один вопрос , хоть и не в тему , но создавать новый топик не хочется.Есть вот такой код:
[code=cpp] #include <iostream.h> #include <string.h> class Person { public: Person(char *pN) { cout << "Sozdayom " << pN << "\n"; pName = new char[strlen(pN) + 1]; if (pName != 0) { strcpy(pName, pN) ; } } ~Person() { cout << "Likvidiruem " << pName << "\n"; pName[0] = '0'; cout << pName << "\n"; delete pName; cout << pName << "\n"; } char *pName; }; void fn() { Person p1 ("Stroka"); Person p2 = p1; } int main(int argcs, char* pArgs[]) { fn(); int d; cin >> d; return 0; } [code=cpp] Вопрос в следующем каким образом указатель pName превратился в массив pName[0] и почему в этом массиве можно присвоить значение только первому элементу , т.е. pName[1] = '0' не работает? |
|||
|
||||
nikitao |
|
||||||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 1 Всего: 26 |
Guest ,у тебя неправельно написано прога.Нельзя так приравнивать обьекты собственного класса в которых используется динамика(Person).Для этого надо перегрузить оператор '='.Дело в том что когда ты приравниваешь(без перегрузки) два обьекта произходит побитовое копирование одного обьекта в другой т е произходит копирование указателя,но не строки
![]() ![]() ![]() ![]() Ошибка возникает в том что в конце ф-ции fn() вызывается 2 деструктора(для p1 и p2),но когда срабатывает деструктор для p2 строка уже удалена деструктором p1(указатели же указывают на один участок).Так что надо доработать. Надо писать не
а
Поскольку это массив
Этого я не понял,все работает если написать pName[1]. ![]() -------------------- Жизнь - печальная штука. |
||||||
|
|||||||
Guest |
|
||||
Unregistered |
nikitao , да не , я в курсе , просто это немного переделанный пример из книги. Правильно будет вот так :
Как ни странно у меня тоже заработало. |
||||
|
|||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
Вопрос в тему.
Можно ли выделить память опером new для глобального массива? И если да, то где юзать delete[]... -------------------- people can fly |
|||
|
||||
nikitao |
|
||||||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 1 Всего: 26 |
Все равно не верно(но тут уже мелочи:
1.Почему то во 2 конструкторе нужная длина массива высчитывется првельно а в 1-нет(единицу не прибавили) 2.То что перегружен конструктор не перегружает оператор '='.Соответственно вместо
должно быть
3.Ты так и не исправил ошибку с delete(это про '[]') Добавлено @ 22:18 Helicopterr,да можно,а юзать delete можно где хочешь(можно даже вообще не юзать,но тогда утечка произойдет).Если тебе надо чтоб в самом конце удалялось,то перед
надо писать.И вообще перед каждым return 0 и exit() в ф-ции main это надо будет прописать. -------------------- Жизнь - печальная штука. |
||||||
|
|||||||
S.A.P. |
|
||||||||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2664 Регистрация: 11.6.2004 Репутация: 9 Всего: 71 |
аналогичны. Добавлено @ 01:12
delete[] юзается где угодно. Добавлено @ 01:16
как раз тут и не обязательно. Ось сама грохнет всю кучу по завершении программы. Исключение может составлять вызовы деструкторов у объектов в куче, которые должны выполнить какие - то завершающие действия. Это сообщение отредактировал(а) Perchilla - 4.12.2005, 01:13 |
||||||||||
|
|||||||||||
maxim1000 |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
для нормального вызова деструкторов можно сделать так: делаем глобальный объект, у него одно поле - указатель в конструкторе выделяем, в деструкторе освобождаем... -------------------- qqq |
||||
|
|||||
oberonchik |
|
|||
![]() Новичок Профиль Группа: Участник Сообщений: 8 Регистрация: 26.11.2005 Репутация: нет Всего: нет |
Я немного вернусь к первому обсуждаемому вопросу в этот посте.
У стека есть ещё одна очень неприятная особенность. Он может медленно расти. Например, был опыт под Linux когда стек рос очень медленно после появления потребности. Т.е. создаются обекты в стеке, а система его наращивает лишь когда появляюся конкретные обращения, причем делает это чуть ли не по 4кб. Проблема была серьёзная, производительность была низкая, а задача была критична к этому. Под другими никсами и виндой всё было ок. А под целевой системой Linux никак. Долго я этот баг ловил. Потом выделил динмически и всё начало летать |
|||
|
||||
Helicopterr |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 355 Регистрация: 20.8.2005 Где: Stavropol Репутация: 2 Всего: 3 |
однако я читал что поток в стеке быстрее и для небольших массивов, я думаю, в аллокации смысла нет
-------------------- people can fly |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 17 Всего: 110 |
обычно (не буду утверждать, что всегда) стек работает быстрее динамической памяти: т.к. он накладывает свои ограничения на порядок создания/удаления объектов - последний созданный удаляется первым
динамическая память не заставляет программиста удовлетворять этому требованию, что приводит у увеличению гибкости и к замедлению выделения/освобождения памяти (из-за различных алгоритмов, связанных с учетом свободного места, которое теперь может быть фрагментированно) сильно подозреваю, что если при использовании динамической памяти все-таки придерживаться политики стека (последний создан - первый удален), эффективность возрастет (правда, динамической памятью часто пользуются именно для того, чтобы создавать и удалять объекты, когда вздумается) но даже тогда на большинстве систем стек, скорее всего, будет быстрее, т.к. он также используется при вызове/возврате из функций, а значит, у него больше шансов оказаться в кеше процессора... -------------------- qqq |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |