Подтвердить что ты не робот

Как выбрать распределение кучи и распределение стека в С++?

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

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

4b9b3361

Ответ 1

Одна из возможностей С++, которая отличает ее от других языков

... заключается в том, что вы должны вручную распределять память. Но оставьте это в стороне:

  • выделять кучу, когда объект должен быть долговечным, т.е. должен пережить определенную область и дорого или невозможно копировать или перемещать,
  • выделять кучу, когда объект является большим (где может потребоваться несколько килобайт, если вы хотите быть в безопасности), чтобы предотвратить переполнение стека, даже если объект нужен только временно,
  • выделять кучу, если вы используете pimpl (компилятор firewall) idiom,
  • выделять массивы переменных размеров в кучу,
  • выделять в стеке иначе, потому что это намного удобнее.

Обратите внимание, что во втором правиле "большим объектом" я имею в виду что-то вроде

char buffer[1024 * 1024];  // 1MB buffer

но не

std::vector<char> buffer(1024 * 1024);

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

Что касается элементов указателя и значения:

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

Использование интеллектуальных указателей, конечно, рекомендуется там, где это необходимо. Обратите внимание, что вы можете использовать ссылку в случае распределения кучи, потому что всегда можете delete &ref, но я бы не рекомендовал это делать. Ссылки - это маскирующие указатели с единственным отличием (ссылка не может быть нулевой), но они также сигнализируют о другом намерении.

Ответ 2

Нельзя добавить ответ от larsmans.

Выделение в стек обычно упрощает управление ресурсами, вам не нужно беспокоиться об утечке памяти или собственности и т.д. Создается библиотека графического интерфейса пользователя вокруг этого наблюдения, отметьте "Все принадлежит где-то" и "Кто владеет виджетами".

Если вы выделяете все элементы в стеке, то обычно достаточно копии ctor по умолчанию и по умолчанию op =. Если вы выделяете членов в кучу, вы должны быть осторожны с тем, как вы их реализуете.

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