Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.53/140: Рейтинг темы: голосов - 140, средняя оценка - 4.53
5 / 5 / 2
Регистрация: 21.07.2016
Сообщений: 34

Стек или куча: как "правильно" создавать объекты классов?

18.02.2017, 05:00. Показов 27693. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
У меня несколько странновато-ламерский вопрос, но ведь в том и смысл: чтобы таких вопросов не осталось, на них один фиг сначала нужно где-то получить ответы.

Когда нужно создавать объекты через указатель, а когда - статично? Я по возможности хочу придерживаться одного стиля, но вот проблема - не знаю какого
C++
1
2
3
4
5
MyClass* c1 = new MyClass();
c1->foo();
 
MyClass c2 = MyClass(); // MyClass с2();
c2.foo();
Что известно мне. То, что в первом случае объект размещается в динамической памяти, а во втором - в статической (т.е. на этапе компиляции). Но что это дает мне, как программисту? Какая мне разница, когда и какая выделяется память для моих переменных? К ним обоим есть доступ, с ними обоими можно работать. А что еще для счастья надо? А если мне эти объекты нужно передавать в качестве аргументов функции, то для второго случая я просто использую передачу по ссылке. Уменьшу себе кол-во стрелочек и звездочек (а заодно и кол-во выстрелов себе в ногу из-за потенциальных проблем с указателями). Получается, что статичная инициализация даже предпочтительнее? Тогда почему именно указатели вижу чаще в коде других людей? Очевидно, я чего-то не знаю, вот и интересно, что именно.

Знаю, что в первом случае для осовобождения памяти применяется delete (ну, по-хорошему). Получается, что для второго случая освобождать память не требуется? Всё потому, что она статична занимается раз и навсегда? Верно?

Также я знаю, что динамическое создание объектов применяется если размер объекта неизвестен. Правда тут во всех примерах упоминают только массивы, и с ними мне как раз всё понятно. Но подобное про класс я ничего нигде не видел. И даже если внутри класса будут те же динамические массивы, почему я все равно могу использовать вторую запись?

Может быть вся "проблема" в этой самой статичной памяти? Перефразируя свой первый вопрос, задам последний вопрос: где, в смысле в какой памяти, предпочтительнее размещать объекты в своих программах, и почему?

Заранее спасибо всем отвечающим. Знаю, вопросы ламерские. И я честно читал умные книжки и статейки, про память, про классы... Но надеюсь вам не составит труда дать исчерпывающие ответы.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.02.2017, 05:00
Ответы с готовыми решениями:

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

Как правильно создавать объекты ?
Как правильно создавать объекты и как они расходуют память, что является правильным подходом? public class MyClass extends Activity { ...

Как правильно создавать объекты на форме?
Задача следующей программы рисовать гибкий график функции на поле класса PictureBox. Для этого я создал класс, в котором объявляется объект...

27
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
18.02.2017, 12:12
Студворк — интернет-сервис помощи студентам
Renji, В общем-то я с вами согласен. Вот у меня есть такая привычка. Все диалоги (модальные) создаю в стеке. Ибо их жизнь ограничивается телом метода, в котором они вызваны. Поговорил - и хватит. Но все их подвиджетики, конечно, в куче. И все остальное, чья жизнь зависит от каприза пользователя, тоже туда же.
1
187 / 54 / 19
Регистрация: 23.12.2016
Сообщений: 167
18.02.2017, 12:21
Статичные объекты создаются статично, динамичные - через вызов new. Т.е. если объект не изменяется во время рантайма, то можно и просто объявить экземпляр объекта. Если же объект класса изменяется - т.е. удаляется и вместо него генерируется другой объект того же класса - то через new и указатель. Это общее правило, которому я обычно следую.
Но есть нюансы. Иногда в другие классы нужно передать указатель на другие классы - это если они тесно взаимодействуют. Это гораздо проще сделать, если объявлять объекты динамически - мы сразу имеем указатель на объект без лишних телодвижений. Паттерн "Фабричный метод", который применяется почти везде - только через указатели работает. Ну и т.д. Да и вообще Computer Science движется в сторону указателей. В Java всё работает по сути через указатели, интерфейс только чуть другой чем в С++.
Хотя если создается много объектов одного класса - это проще решить через массив объектов, чем через массив указателей - меньше кода писать.
Это всё сугубо мое мнение.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
18.02.2017, 14:24
Цитата Сообщение от Lyosha12 Посмотреть сообщение
Если кратко, с помощью них организовывается полиморфное поведение в программе. Правда, его можно организовать и с помощью ссылок, но этот момент мне менее понятен
У указателей в данном контексте есть определенное преимущество. В случае с указателями есть возможность объявить указатель на базовый класс но присвоить ему значение позже. С ссылками такое не прокатит, потому что они должны быть инициализированы в момент объявления.
1
 Аватар для Lyosha12
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
18.02.2017, 14:28
Цитата Сообщение от sys_beginner Посмотреть сообщение
У указателей в данном контексте есть определенное преимущество. В случае с указателями есть возможность объявить указатель на базовый класс но присвоить ему значение позже. С ссылками такое не прокатит, потому что они должны быть инициализированы в момент объявления.
Тогда отличий, получается, нет? Философия остаётся той же: ссылка есть автоматически разыменованный указатель?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
18.02.2017, 14:54
Цитата Сообщение от Lyosha12 Посмотреть сообщение
Тогда отличий, получается, нет?
Единственное сходство на мой взгляд лишь в том, что и ссылки и указатели работают с одним и тем же участком памяти которую занимает используемый объект.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
struct Foo
{
    int n ;
};
 
void foo(Foo &f)
{
    f.n = 300;
}
 
int main()
{
    Foo *f = new Foo();
    f->n = 200;
    foo(*f);
    std::cout << f->n;
}
В общем указатели более функциональны нежели ссылки.
1
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
18.02.2017, 16:45
Лучший ответ Сообщение было отмечено gru74ik как решение

Решение

Цитата Сообщение от Lyosha12 Посмотреть сообщение
Тогда отличий, получается, нет? Философия остаётся той же: ссылка есть автоматически разыменованный указатель?
Попробуйте продлить время жизни
временного объекта с помощью указателя.
Когда получится, напишите нам об этом.

Цитата Сообщение от JavaFX2 Посмотреть сообщение
Когда нужно создавать объекты через указатель, а когда - статично?
Введем для этого пояснения такое понятие, как время жизни объекта (object lifetime).
Будем считать, что объект начинает жизнь тогда, когда под
него выделилась память и завершилась его инициализация.
Всякие отводы, тонкости и заковыки рассматривать не будем.

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


Итак, для начала рассмотрим коротенько четыре "времени хранения" (storage duration).

Статическое время хранения (static storage duration) - всё статическое живет от момента
создания до самого конца программы.

Потоковое время хранения (thread storage duration) - всё потоковое живет от момента
создания до конца потока в котором создано.

Автоматическое время хранения (automatic storage duration) - всё автоматическое живет от момента
создания до конца блока в котором оно было создано.

Динамическое время хранения (dynamic storage duration) - всё динамическое живет от момента
создания до того момента, пока его явно не прихлопнут.


Соответственно уже отсюда можно сделать вывод что нам необходимо.
A. Если объект должен жить всю программу (ну, почти), то варианта два:
1) Использовать объект с потоковым временем хранения,
ежели у нас имеется один, живущий всю программу поток.
2) Использовать объект с статическим временем хранения.
0) Еще вариант, использовать динамический объект,
но для его корректного уничтожения придется либо
в какой-то из функций его явно уничтожить, что как бы
уже подразумевает, что объект живет меньше чем статические объекты,
либо же в деструкторе одного из статических объектов уничтожить и наш
динамический объект, только вот получается, что нам для этого
нужен статический объект, так что такой вариант не рассматриваем.
Вариант не уничтожать его совсем - система прихлопнет память,
рассматривать не будем, т.к. для объектов не будет вызван деструктор,
а мы рассматриваем общее для всех объектов, а не отдельных их "видов".
Так что для "чистоты эксперимента" подобные варианты мы не рассматриваем.
Также выбросим из повествования временные объекты.


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


C. Если нам нужен объект, который должен быть уничтожен
после выхода из блока, в котором создался, то варианта два:
1) Использовать автоматический объект.
2) Использовать динамический объект, но при этом
придется вручную его создавать и уничтожать.


D. Если нам необходимо, чтобы объект, созданный в блоке жил
до самого конца программы (или потока),то вариант у нас один:
1) Сделать его статическим объектом, ну или потоковым, если речь о потоке.
0) С динамическим объектом та же фигня, что и в прошлый раз -
до конца такое не доживет, либо уничтожится не правильно (в общем случае).


E. Если нам необходимо, чтобы объект жил после выхода из блока в
котором создан, но мы не знаем до какого времени он нам понадобится и,
жить ему всю программу не нужно, то здесь вариант тоже один:
1) Динамический объект.


Теперь по каждому пункту отдельно.

A. Потоковый или статический?
А смотрим на программу. У нас планируется всего один поток?
Если да, то нефиг пытать потоковый класс памяти.
Если же потоков может быть несколько,
то у каждого потока должна быть своя такая переменная?
Если да, то потоковый берем, если нет - статический.


B. см. предыдущий пункт.


C. Автоматический или динамический?
Объекты маленькие, их количество известно и они точно влезут в стек (без фанатизма)?
Если да то использовать автоматические объекты или динамические
зависит от хотелок разработчика и здравого смысла.
Если не нужна динамика, то нафиг заниматься ручной работой?
Но если очень хочется, то можно хоть каждый int делать динамическим.
Если же объекты тяжелые и не хочется на них тратить стек,
или же нам неизвестно конечное количество одновременно
живущих элементов, то тут только динамические объекты прокатят.
Вариант "создам здоровый массив на все случаи жизни"
здесь не прокатит, т.к. выше оговорено, что конечное количество одновременно
живущих объектов неизвестно и, соответственно, оно всегда будет равно sizeof(mySuperArray)/sizeof(*mySuperArray) + 1.


D. Всё как и прежде - смотрим на потребности в каждом потоке.


E. Без вариантов.


В программах, чаще всего, встречается смесь из всего
высказанного выше в разных пропорциях и сочетаниях.


Вот такая абсолютно бесполезная портянка,
т.к. она всё равно не покрывает всего и вся
и не является истиной в последней инстанции.
9
 Аватар для Lyosha12
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
18.02.2017, 16:53
Цитата Сообщение от Croessmah Посмотреть сообщение
Попробуйте продлить время жизни
временного объекта с помощью указателя.
Когда получится, напишите нам об этом.
О, контекст, великий и всемогущий! Да, всё, что Вы сказали - просто описали моё интуитивное поведение при выборе места, куда поместить объект. Я же говорил об отличиях ссылки от указателя при реализации полиморфного поведения

Добавлено через 45 секунд
Цитата Сообщение от Croessmah Посмотреть сообщение
Также выбросим из повествования временные объекты.
А жаль, про могло бы быть самое интересное чтиво, ведь именно с такого рода объектами мне не до конца всё понятно: это я про и оптимизации, и про std::move()
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
18.02.2017, 16:58
Цитата Сообщение от Lyosha12 Посмотреть сообщение
Я же говорил об отличиях ссылки от указателя
А я отвечал на вопрос ТС
Цитата Сообщение от JavaFX2 Посмотреть сообщение
Когда нужно создавать объекты через указатель, а когда - статично?
поэтому специально пару лишних строк пропустил.
правда тут явное несоответствие в вопросе.

Цитата Сообщение от Lyosha12 Посмотреть сообщение
А жаль, про могло бы быть самое интересное чтиво
Оно будет вне заданной тематики.

Добавлено через 1 минуту
Цитата Сообщение от Lyosha12 Посмотреть сообщение
это я про и оптимизации, и про std::move()
Про это планируется блог...
Ну, собственно, давно уже планируется,
увы, но времени нет на такую писанину.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.02.2017, 16:58
Помогаю со студенческими работами здесь

Как правильно создавать экземпляры классов?
#!C:\starwberry\perl\bin\perl.exe use strict; use warnings; { package MyStack; sub new { my $class = shift;

Где создавать объекты классов?
Здравствуйте. Подскажите, если есть много классов, объявленных в заголовочных файлах, а определенных в *.cpp - файлах, и для каждого...

Возможно ли создавать объекты для абстрактных классов?
Можете дать ответ на вопрос: Возможно ли создавать объекты для абстрактных классов?

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

Считается ли хорошим тоном создавать объекты классов в области глобальных переменных
Считается ли хорошим тоном создавать объекты классов в области глобальных переменных? class FX { ........ ......... };


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

Или воспользуйтесь поиском по форуму:
28
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru