Как выбрать распределение кучи и распределение стека в C ++? - PullRequest
17 голосов
/ 02 ноября 2011

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

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

Ответы [ 2 ]

22 голосов
/ 02 ноября 2011

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

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

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

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

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

, но не

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

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

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

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

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

2 голосов
/ 02 ноября 2011

К ответу larsmans добавить нечего.

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

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

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

...