Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 38, средняя оценка - 4.79
SergBokh
82 / 74 / 2
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 15:40     Стек и динамическая память #1
Читаю книжку по с++. Для хранения переменных может использоваться стек или динамическая память.

чтоб поместить в стек нужно объявить так:
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. Почему нужно размещать объекты в динамической памяти, а не в стек? Ограниченность стека?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.12.2010, 15:40     Стек и динамическая память
Посмотрите здесь:

C++ Динамическая память
C++ Динамическая память и стек,различие
C++ Динамическая память
C++ Динамическая память
C++ Динамическая память
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
04.12.2010, 16:02     Стек и динамическая память #2
1. Как уничтожать объекты, помещенные в стек? Насколько я понял деструктор вызывается автоматически при выходе за пределы видимости, и память освобождается.
Да.

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

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

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

Добавлено через 9 минут
В принципе, можно было бы придумать язык (организацию памяти), чтобы все new помещались в стек. Но если тебе надо что-то создать в функции и вернуть в вызывающую ? Ведь при выходе из функции весь стек теряется. И вместе с ним теряется гибкость языка.
SergBokh
82 / 74 / 2
Регистрация: 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?
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
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 
    // Джери и его голова в динамической.
 
}
SergBokh
82 / 74 / 2
Регистрация: 03.09.2009
Сообщений: 346
04.12.2010, 19:55  [ТС]     Стек и динамическая память #7
>> Выбор зависит от того что вы хотите сделать.

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

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

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

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

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

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

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

вот собственно пример статического и динамического выделения памяти.
Day
 Аватар для Day
1149 / 954 / 57
Регистрация: 29.10.2009
Сообщений: 1,384
04.12.2010, 21:14     Стек и динамическая память #9
Кстати сам процесс деструктора ведь не разрушает объект, а только разрешает использовать эту память в будущем. Т.е. некоторое время после разрушения еще можно пользоваться объектом по указателю? ))
Я бы не рискнул. Хотя молодежь у нас отчаянная.
Кстати, м.б. это и имеет какой-то смысл. Например, в играх. Элемент неожиданности. Чтоб нервы разработчику пощекотать...
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
04.12.2010, 21:20     Стек и динамическая память #10
Цитата Сообщение от Day Посмотреть сообщение
Кстати, м.б. это и имеет какой-то смысл. Например, в играх. Элемент неожиданности. Чтоб нервы разработчику пощекотать...
оффтоп:

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

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

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

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

Непривычно после managed-кода.
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
05.12.2010, 00:32     Стек и динамическая память #14
это уже скорее философский вопрос

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

зы: счас схватим от модеров за офтоп...
SergBokh
82 / 74 / 2
Регистрация: 03.09.2009
Сообщений: 346
05.12.2010, 20:26  [ТС]     Стек и динамическая память #15
А как объявить массив указателей, чтоб он создался в динамической памяти? голову сломал
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
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];
SergBokh
82 / 74 / 2
Регистрация: 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 **'
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.12.2010, 02:09     Стек и динамическая память
Еще ссылки по теме:

Статическая память,Динамическая память. C++
C++ Стек или динамическая память!?
Динамическая структура данных (Стек) C++

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

Или воспользуйтесь поиском по форуму:
Vladimir.
155 / 155 / 10
Регистрация: 24.11.2009
Сообщений: 375
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 ;      //удаляем массив указателей на инт
}
Yandex
Объявления
06.12.2010, 02:09     Стек и динамическая память
Ответ Создать тему
Опции темы

Текущее время: 06:55. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru