Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.64/39: Рейтинг темы: голосов - 39, средняя оценка - 4.64
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
1

Стек и динамическая память

04.12.2010, 15:40. Показов 7147. Ответов 17
Метки нет (Все метки)

Читаю книжку по с++. Для хранения переменных может использоваться стек или динамическая память.

чтоб поместить в стек нужно объявить так:
C++
1
2
int i; // переменная int
Cat cat; // объект класса Cat
Чтоб поместить в дин. память:
C++
1
2
int * p_i = new int;
Cat * pCat = new Cat;
Вроде понятно, но после C# возникает несколько вопросов:

1. Как уничтожать объекты, помещенные в стек? Насколько я понял деструктор вызывается автоматически при выходе за пределы видимости, и память освобождается.

2. если класс Cat имеет такой вид:
C++
1
2
3
4
5
class Cat
{
    CatHead catHead; // класс, объявленный "методом стека"
    ...
};
и мы размещаем объект Cat в дин.памяти. Выходит тело объекта Cat будет размещено в динамической памяти, а часть объекта Cat (catHead) - в стековой памяти?

3. Почему нужно размещать объекты в динамической памяти, а не в стек? Ограниченность стека?
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.12.2010, 15:40
Ответы с готовыми решениями:

Стек или динамическая память!?
Добрый вечер всем! Прошу ответить на вопрос (ниже приведен код): почему строка "Test!" выводится на...

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

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

Статическая память,Динамическая память.
a) Статическая память. Двумерный массив. Дан массив целых чисел. В массиве есть отрицательные...

17
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
04.12.2010, 16:02 2
1. Как уничтожать объекты, помещенные в стек? Насколько я понял деструктор вызывается автоматически при выходе за пределы видимости, и память освобождается.
Да.

2. если класс Cat имеет такой вид
...
и мы размещаем объект Cat в дин.памяти. Выходит тело объекта Cat будет размещено в динамической памяти, а часть объекта Cat (catHead) - в стековой памяти?
всё будет в динамической.

3. Почему нужно размещать объекты в динамической памяти, а не в стек? Ограниченность стека?
при запуске программы для её объектов резервируется место в памяти. Однако некоторые объекты могут иметь переменный или неизвестный при запуске объем (например, структуры данных). Поэтому для них память выделяется в процессе работы программы, то есть "динамически"
1
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 16:42  [ТС] 3
Цитата Сообщение от Vladimir. Посмотреть сообщение
2. всё будет в динамической.
Т.е. внутри своего класса можно не заморачиваться с размещением объекта в динамической памяти, а объявлять объекты коротким способом: CatHead catHead;
И при этом все-равно эти подклассы разместятся в динамической памяти (при условии, что основной класс-контейнер Cat размещен в динамической памяти через команду "new")

Цитата Сообщение от Vladimir. Посмотреть сообщение
при запуске программы для её объектов резервируется место в памяти. Однако некоторые объекты могут иметь переменный или неизвестный при запуске объем (например, структуры данных). Поэтому для них память выделяется в процессе работы программы, то есть "динамически"
Ну так а что случится, если все объекты в программе объявлять не через команду "new", а просто как переменные?
0
Day
1176 / 986 / 83
Регистрация: 29.10.2009
Сообщений: 1,385
04.12.2010, 17:00 4
SergBokh, Если ты сможешь решить свою задачу, не используя дин.памяти - Бог тебе в помощь.
Но я не вижу ни одной задачи (не считая школьных) где можно было б обойтись одним стеком.
Как правило, размеры массивов при написании проги - неизвестны.

Добавлено через 9 минут
В принципе, можно было бы придумать язык (организацию памяти), чтобы все new помещались в стек. Но если тебе надо что-то создать в функции и вернуть в вызывающую ? Ведь при выходе из функции весь стек теряется. И вместе с ним теряется гибкость языка.
1
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 18:33  [ТС] 5
>>Но если тебе надо что-то создать в функции и вернуть в вызывающую ? Ведь при выходе из
>>функции весь стек теряется. И вместе с ним теряется гибкость языка.

Да, точно, если функция и вернет ссылку на созданный объект, то это будет ссылка на уже разрушенный объект.

Кстати сам процесс деструктора ведь не разрушает объект, а только разрешает использовать эту память в будущем. Т.е. некоторое время после разрушения еще можно пользоваться объектом по указателю? ))

------------------------------------------------

И остался непонятным такой момент - есть ли разница в объявлении объектов внутри объекта-контейнера:
class Cat
C++
1
2
3
4
5
{
   CatHead catHead; // объект внутри объекта Cat. 
                                 // разместится этот объект где??? в стеке или в динамической памяти?
                                 // уничтожится ли этот объект автоматом при уничтожении Cat???
};
и так:

C++
1
2
3
4
5
class Cat
{
   CatHead * p_catHead = new CatHead; // объект внутри объекта Cat
                                                                  // этот объект нужно будет уничтожить вручную в деструкторе Cat
};
Или можно и так и так, если не предполагается использовать объект CatHead после уничтожения Cat?
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
04.12.2010, 19:46 6
Цитата Сообщение от SergBokh Посмотреть сообщение
Кстати сам процесс деструктора ведь не разрушает объект, а только разрешает использовать эту память в будущем. Т.е. некоторое время после разрушения еще можно пользоваться объектом по указателю? ))
деструктор освобождает память, то есть любая другая программа на машине в любой момент может забисать в эту область памяти свои данные.
Цитата Сообщение от SergBokh Посмотреть сообщение
И остался непонятным такой момент - есть ли разница в объявлении объектов внутри объекта-контейнера:

Или можно и так и так, если не предполагается использовать объект CatHead после уничтожения Cat?
деструктор Cat в процессе своей работы вызовет деструктор для CatHead. Выбор зависит от того что вы хотите сделать.

Добавлено через 29 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class heads{};
 
class cats{
    heads cat_head;
    public:
        cats(){};
        ~cats();
    
}
 
class dogs{
    heads* dog_head;
    public:
        dogs(){dog_head = new dog_head;};
        ~dogs(){delete dog_head};
    
}
 
main(){
    cats Tom;
    // Кот том в стэке, его голова там же.
    cats* Fluffy = new cats;
    // Кот Флаффи в динамической памяти вместе со своей головой.
    dogs Charly;
    // Чарли в статической, а его голова в динамической.
    dogs* Jerry 
    // Джери и его голова в динамической.
 
}
1
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 19:55  [ТС] 7
>> Выбор зависит от того что вы хотите сделать.

Так я не пойму в чем разница между 2-мя этими способами объявления. Даже 1-й способ лучше, т.к. вложенные объекты уничтожатся автоматом, не нужно об этом заботиться.
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
04.12.2010, 20:20 8
Цитата Сообщение от SergBokh Посмотреть сообщение
>> Выбор зависит от того что вы хотите сделать.

Так я не пойму в чем разница между 2-мя этими способами объявления. Даже 1-й способ лучше, т.к. вложенные объекты уничтожатся автоматом, не нужно об этом заботиться.
Верно. А разница не очевидна потому, что мы разбираем отвлечённые вещи. Давайте разберём какой нибудь пример - умножим векторы.

Пусть нам нужно создать класс который описывает поведение следующего объекта:

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

Для того что бы реализовать второй пункт нам в нашем классе нужно описать две переменные -
для скалярного и векторного произведений - и функции для обращения к ним.

размер скалярного произведения - одна переменная типа double. И память для неё можно выделить статически.

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

вот собственно пример статического и динамического выделения памяти.
0
Day
1176 / 986 / 83
Регистрация: 29.10.2009
Сообщений: 1,385
04.12.2010, 21:14 9
Кстати сам процесс деструктора ведь не разрушает объект, а только разрешает использовать эту память в будущем. Т.е. некоторое время после разрушения еще можно пользоваться объектом по указателю? ))
Я бы не рискнул. Хотя молодежь у нас отчаянная.
Кстати, м.б. это и имеет какой-то смысл. Например, в играх. Элемент неожиданности. Чтоб нервы разработчику пощекотать...
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
04.12.2010, 21:20 10
Цитата Сообщение от Day Посмотреть сообщение
Кстати, м.б. это и имеет какой-то смысл. Например, в играх. Элемент неожиданности. Чтоб нервы разработчику пощекотать...
оффтоп:

А игра будет называться останься без премии....

Фактически в 95% случаев в реальных задачах делается так, что указатель исчезает вместе с объектом. В любом случае при удалении объектов этот момент нужно контролировать хотя бы через ptr = NULL.
0
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 21:59  [ТС] 11
Понятно. Только остается какое-то подозрение, что в книжке не совсем верно написано про размещение в стеке и динамической памяти. Скорее в статической части и в динамической.

кстати, если вызвать деструктор для объекта, размещенного статически - эта память освободится для других данных или нет?
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
04.12.2010, 22:08 12
в книге правильно написано.
там имеется ввиду программный стэк операционной системы, для программы это будет статической памятью.

не знаю, но думаю что нет. Скорее всего это зависит опять-таки от ОС.
0
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 22:54  [ТС] 13
Это очень забавно, когда объект убивается, но какое-то время полностью функционален. А возможно он даже неубиваем, если расположен в статической памяти.

Непривычно после managed-кода.
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
05.12.2010, 00:32 14
это уже скорее философский вопрос

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

зы: счас схватим от модеров за офтоп...
0
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
05.12.2010, 20:26  [ТС] 15
А как объявить массив указателей, чтоб он создался в динамической памяти? голову сломал
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
05.12.2010, 20:43 16
а как объявить массив чего либо в динамической памяти?

some_type* ptr = new some_type [size];

если нужен массив указателей тип some_type должен быть типом указателей на что-то, например для int some_type = int*

массив указателей на int в динамической памяти:
int** ptr = new int** [size];
0
85 / 77 / 13
Регистрация: 03.09.2009
Сообщений: 346
06.12.2010, 01:05  [ТС] 17
Не получается так.
Даже первое утверждение - массив int в динамической памяти - не работает:

int * ptr = new int [10];

Компилируется, но работает странно - так же как и одиночная переменная, если бы она была бы объявленна так : int * ptr = new int;
То ли я не умею правильно разименовывать массив?

Такой же вариант:
int** ptr = new int** [size];
не компилируется - cannot convert 'int ***' to 'int **'
0
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
06.12.2010, 02:09 18
Цитата Сообщение от SergBokh Посмотреть сообщение
Такой же вариант:
int** ptr = new int** [size];
не компилируется - cannot convert 'int ***' to 'int **'
это описка =)
если:
some_type* ptr = new some_type [size];
то поскольку под some_type мы понимаем int* :
int** ptr = new int* [size];

То ли я не умею правильно разименовывать массив?
проверте себя:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<iostream>
 
int main(void){
 
    int** ptr;
    int dimension = 2;
    ptr = new int* [dimension];     //массив указателей на инт
        for (int i=0; i<dimension; i++)
            ptr[i]= new int;        //каждому указателю по инту
    // теперь до интов можно добраться только через указатель.
 
    int a = 5;
    int b = 10;
    
    **ptr = 5; 
    **(ptr+1) = 10;
    
    std::cout<<*(ptr[0])<<'\t'<<*(ptr[1])<<std::endl;
    
    delete ptr[0];      //удаляем инты
    delete ptr[1];
    delete[] ptr ;      //удаляем массив указателей на инт
}
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.12.2010, 02:09

Динамическая структура данных (Стек)
Подскажите в чем ошибка, пожалуйста. Программа выдает ошибку (&quot;Прекращена работа программы..&quot;),...

Динамическая память
Всем привет!!! взникла проблема с выполнением строки K=A++; при выполнении...

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

Динамическая память
int set_arr(char* arr, int size, int pos, char* str) { if (pos &lt;0 || size &lt;= 0) { return 1;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru