Как выбирать где создавать экземпляры класса, в динамической памяти или на стеке?

Рейтинг: 1Ответов: 2Опубликовано: 20.01.2023

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

Единственное правильно, которое я обнаружил: в main-e я выделяю объекты в стеке(только если они не синглтон, как конфиг например)(но их там собственно не очень много, менее 5 штук - конфиг, работа основного алгоритма, запись результатов в бд. Вот уже внутри алгоритма и бд полнейший хаос). Можно добавить то, что если объект класса мне нужен только в пределах метода, то тоже не выделяю динамически(хотя наверное, если метод вызывается n раз стоило бы данный объект хранить в классе).

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

Ответы

▲ 4Принят

Всегда на стеке, если нет какой-то конкретной причины использовать кучу.

Возможные причины:

  • Это массив переменного размера - в стандартном С++ их нельзя создать на стеке.
  • Объект должен пережить выход из функции, где был создан. Причем пережить в своем оригинальном виде, а не как returnутая копия.
  • Объект слишком большой. (Несколько килобайт? При размере стека в единицы мегабайт.)
  • ...?

И как правильно пишет @StanislavVolodarskiy, в вашем коде не должно быть new и delete. Это низкоуровневые инструменты для авторов контейнеров и умных указателей: std::vector, std::unique_ptr и подобных. Используйте их вместо new и delete.

▲ 1

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

Иногда(для примера) может быть уместно создать свою собственную тривиальную хэш_таблицу, чем пользоваться стандартным. Существующий любой способ хранения имеет свои преимущества и недостатки, но если не нужно будет выращивать контейнер или удалять некоторые объекты по ходу, то логично их хранить статически в таких, как std::valarray std::array..., в собственноручно написанном или стандартном, но точно не в векторе или других контейнерах, которые используют динамическую память, просто потому что это дороже и не специфично для данного метода. Нет общих правил дизайна и архитектуры _ каждому свое...