Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> динамическая память и массивы 
:(
    Опции темы
bern
Дата 2.12.2005, 23:54 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Здраствуйте! У меня к вам такая просьба - объясните мне пожалуйста чем таким кардинальным отличается динамическая память от массивов и что можно сделать с помощью new&delete чего нельзя было бы сделать с помощью массивов? Ведь в динамической памяти точно также выделяется место под отдельные переменные и массивы, так в чём разница ? И вообще почему этот метод называется динамическим?

  Вверх
blackofe
Дата 3.12.2005, 00:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 173
Регистрация: 29.11.2005

Репутация: 4
Всего: 4



Цитата(bern @ 2.12.2005, 23:54)
Здраствуйте! У меня к вам такая просьба - объясните мне пожалуйста чем таким кардинальным отличается динамическая память от массивов и что можно сделать с помощью new&delete чего нельзя было бы сделать с помощью массивов? Ведь в динамической памяти точно также выделяется место под отдельные переменные и массивы, так в чём разница ? И вообще почему этот метод называется динамическим?

в c++ массивы должны иметь константную размерность. динамическое выделение памяти позволяет объявить массив произвольного размера (который, вообще говоря, не известен на этапе компиляции).
PM MAIL   Вверх
Dray
Дата 3.12.2005, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Материалист
**


Профиль
Группа: Участник
Сообщений: 652
Регистрация: 7.10.2003
Где: г. Всеволожск

Репутация: 2
Всего: 6



Если делаешь так:
Код

int a = 0;

То а создается в стеке.
Если так:
Код

int *a = new int;
*a=0;
delete a;

То а создается в куче.
Разница в том, что переполнение стека куда реальнее чем переполнение кучи.
Вообще указатели и динамическое распределение памяти чаще используются для структур данных самодельных например в списках:
Код

class CNode
{
public:
 int data;
 CNode *pNext;
 CNode ()
 {
  data = 0;
  pNext = NULL;
 };
};

void main (void)
{
 CNode node;
 node->data = 12; //Например
 node->pNext = new CNode;
 //Вообще это отдельная тема
};

Если интересно про списки то лучше воспользоваться поиском. Это уже обсуждалось.
Динамической она называется поскольку количество требуемой памяти определяется во время выполнения программы. Например при создании масива так:
Код

const n = 10;
int mas[n];

Нужно заранее знать кол-во элементов массива. И использовать только константу.
А если так:
Код

int mysize = 0;
cin >> misize;
int *mas = new int[mysize];

Не обязательно знать колличество элементов заранее можно ввести прям с клавиатуры. Память распределяется динамически.


--------------------
忍者

user posted image
PM MAIL   Вверх
Aleksandor
Дата 3.12.2005, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Практик
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 22.11.2005
Где: россия, зеленогра д

Репутация: 0
Всего: 12



Динамический способ рулит потому что-
а) экономит память (и за счет этого повышает быстродействие программы). Часто это вообще критично для программы.
б) не загромождает стек - массив (статический) как любая другая переменная передается в стеке и если он велик то произойдет переполнение стека отведенного потоку и приложение рухнет smile

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

new только один из способов, в Win API используем HeapAlloc и VirtualAlloc

Пример недостатки статического выделения памяти-
char array[1000][1000]; // массив 1000 строк по 1000 байт каждая

- если массив не в глобальной памяти, то он вызовет переполнение стека
- каждая строка может содержать всего 1 символ (+нулевой байт), итого 2 байта.
остальные 998000 байт расходуются впустую
- длина строки может превысить 1000 байт, тогда мы не сможем впихнуть ее в массив
- мы можем не знать заранее сколько строк потребуется, может всего одна, а может 1001,
в первом случае мы зря расходуем до 999998 байт, во втором вообще труба. Нельзя всунуть больше 1000 строк в этот массив!

Динамическое выделение памяти снимает все эти проблемы smile



Это сообщение отредактировал(а) Aleksandor - 3.12.2005, 11:01


--------------------
Call out Gouranga be happy!!!
Gouranga Gouranga Gouranga ....
That which brings the highest happiness!!
PM MAIL   Вверх
maxim1000
Дата 3.12.2005, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



ну и контроль времени жизни еще можно упомянуть
с точки зрения памяти время жизни - время, когда объект занимает память
в случае использования стека время жизни контролируется тем, когда выполнение входит в блок, в котором объявлен объект, и тем, когда выходит

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


--------------------
qqq
PM WWW   Вверх
Guest
Дата 3.12.2005, 19:23 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


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
Дата 3.12.2005, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кот-программист
***


Профиль
Группа: Завсегдатай
Сообщений: 1206
Регистрация: 30.8.2005
Где: Спб

Репутация: 1
Всего: 26



Guest ,у тебя неправельно написано прога.Нельзя так приравнивать обьекты собственного класса в которых используется динамика(Person).Для этого надо перегрузить оператор '='.Дело в том что когда ты приравниваешь(без перегрузки) два обьекта произходит побитовое копирование одного обьекта в другой т е произходит копирование указателя,но не строки smile smile smile .Получается,что два разных указателя в 2 разных обьектах(p1 и p2) указывают на один участок памяти smile
Ошибка возникает в том что в конце ф-ции fn() вызывается 2 деструктора(для p1 и p2),но когда срабатывает деструктор для p2 строка уже удалена деструктором p1(указатели же указывают на один участок).Так что надо доработать.

Надо писать не
Код

delete pName;

а
Код

delete []  pName;

Поскольку это массив


Цитата(Guest @ 3.12.2005, 20:23)
Вопрос в следующем каким образом указатель pName превратился в массив pName[0] и почему в этом массиве можно присвоить значение только первому элементу , т.е. pName[1] = '0' не работает?

Этого я не понял,все работает если написать pName[1]. smile



--------------------
Жизнь - печальная штука.
PM MAIL ICQ Skype GTalk   Вверх
Guest
Дата 3.12.2005, 21:57 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











nikitao , да не , я в курсе , просто это немного переделанный пример из книги. Правильно будет вот так :
Код

#include <iostream.h>
#include <string.h>

class Person
{
public:
Person(const Person& p)
{
pName = new char[strlen(p.pName)] ;
if (pName != 0)
{
strcpy(pName, p.pName);
}
}
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] = '1';
cout << pName << "\n";
delete pName;
cout << pName << "\n";
}

char *pName;
};

void fn() {
Person p1 ("Randy");
Person p2 = p1;
 }

int main(int argcs, char* pArgs[])
{
fn();
int d;
cin >> d;
return 0;
}


Цитата
Этого я не понял,все работает если написать Name[1].


Как ни странно у меня тоже заработало.

  Вверх
Helicopterr
Дата 3.12.2005, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 355
Регистрация: 20.8.2005
Где: Stavropol

Репутация: 2
Всего: 3



Вопрос в тему.
Можно ли выделить память опером new для глобального массива? И если да, то где юзать delete[]...


--------------------
people can fly
PM MAIL   Вверх
nikitao
Дата 3.12.2005, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кот-программист
***


Профиль
Группа: Завсегдатай
Сообщений: 1206
Регистрация: 30.8.2005
Где: Спб

Репутация: 1
Всего: 26



Все равно не верно(но тут уже мелочи:
1.Почему то во 2 конструкторе нужная длина массива высчитывется првельно а в 1-нет(единицу не прибавили)
2.То что перегружен конструктор не перегружает оператор '='.Соответственно вместо
Код

Person p2 = p1;

должно быть
Код

Person p2 ( p1);

3.Ты так и не исправил ошибку с delete(это про '[]')

Добавлено @ 22:18
Helicopterr,да можно,а юзать delete можно где хочешь(можно даже вообще не юзать,но тогда утечка произойдет).Если тебе надо чтоб в самом конце удалялось,то перед
Код

return 0;
}

надо писать.И вообще перед каждым return 0 и exit() в ф-ции main это надо будет прописать.


--------------------
Жизнь - печальная штука.
PM MAIL ICQ Skype GTalk   Вверх
S.A.P.
Дата 4.12.2005, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 2664
Регистрация: 11.6.2004

Репутация: 9
Всего: 71



Цитата(nikitao @ 3.12.2005, 22:14)
То что перегружен конструктор не перегружает оператор '='.Соответственно вместо
Person p2 = p1;
Person p2 ( p1);
а тут и не обязательно перегружать '='. Это конструктор копирования и в данном случае коды
Код
Person p2 = p1;
и
Код
Person p2 ( p1);

аналогичны.

Добавлено @ 01:12
Цитата(Helicopterr @ 3.12.2005, 22:11)
Вопрос в тему.
Можно ли выделить память опером new для глобального массива? И если да, то где юзать delete[]...
да.

delete[] юзается где угодно.
Добавлено @ 01:16
Цитата(nikitao @ 3.12.2005, 22:14)
И вообще перед каждым return 0 и exit() в ф-ции main это надо будет прописать.

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

Это сообщение отредактировал(а) Perchilla - 4.12.2005, 01:13
PM MAIL   Вверх
maxim1000
Дата 4.12.2005, 04:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



Цитата
Можно ли выделить память опером new для глобального массива? И если да, то где юзать delete[]...

Цитата
Исключение может составлять вызовы деструкторов у объектов в куче

для нормального вызова деструкторов можно сделать так:
делаем глобальный объект, у него одно поле - указатель
в конструкторе выделяем, в деструкторе освобождаем...


--------------------
qqq
PM WWW   Вверх
oberonchik
Дата 4.12.2005, 10:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 26.11.2005

Репутация: нет
Всего: нет



Я немного вернусь к первому обсуждаемому вопросу в этот посте.
У стека есть ещё одна очень неприятная особенность. Он может медленно расти. Например, был опыт под Linux когда стек рос очень медленно после появления потребности. Т.е. создаются обекты в стеке, а система его наращивает лишь когда появляюся конкретные обращения, причем делает это чуть ли не по 4кб.
Проблема была серьёзная, производительность была низкая, а задача была критична к этому. Под другими никсами и виндой всё было ок. А под целевой системой Linux никак. Долго я этот баг ловил. Потом выделил динмически и всё начало летать
PM MAIL   Вверх
Helicopterr
Дата 4.12.2005, 22:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 355
Регистрация: 20.8.2005
Где: Stavropol

Репутация: 2
Всего: 3



однако я читал что поток в стеке быстрее и для небольших массивов, я думаю, в аллокации смысла нет


--------------------
people can fly
PM MAIL   Вверх
maxim1000
Дата 4.12.2005, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: 17
Всего: 110



обычно (не буду утверждать, что всегда) стек работает быстрее динамической памяти: т.к. он накладывает свои ограничения на порядок создания/удаления объектов - последний созданный удаляется первым
динамическая память не заставляет программиста удовлетворять этому требованию, что приводит у увеличению гибкости и к замедлению выделения/освобождения памяти (из-за различных алгоритмов, связанных с учетом свободного места, которое теперь может быть фрагментированно)
сильно подозреваю, что если при использовании динамической памяти все-таки придерживаться политики стека (последний создан - первый удален), эффективность возрастет (правда, динамической памятью часто пользуются именно для того, чтобы создавать и удалять объекты, когда вздумается)
но даже тогда на большинстве систем стек, скорее всего, будет быстрее, т.к. он также используется при вызове/возврате из функций, а значит, у него больше шансов оказаться в кеше процессора...


--------------------
qqq
PM WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1414 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.