Распределение памяти в C ++ - PullRequest
7 голосов
/ 14 января 2011

Я запутался в распределении памяти в C ++ с точки зрения областей памяти, таких как область данных Const, стек, куча, свободное хранилище, куча и глобальная / статическая область. Я хотел бы понять схему распределения памяти в следующем фрагменте. Может ли кто-нибудь помочь мне понять это. Если есть что-то еще, кроме типов переменных, упомянутых в примере, чтобы помочь лучше понять концепцию, измените пример.

class FooBar
{
      int n; //Stored in stack?

      public:

          int pubVar; //stored in stack?

          void foo(int param)  //param stored in stack
          {
                int *pp = new int; //int is allocated on heap.
                n = param;
                static int nStat;  //Stored in static area of memory
                int nLoc;          //stored in stack?
                string str = "mystring"; //stored in stack?
                ..
                if(CONDITION)
                {
                    static int nSIf; //stored in static area of memory
                    int loopvar;     //stored in stack
                    ..
                }
          }
}

int main(int)
{
     Foobar bar;    //bar stored in stack? or a part of it?

     Foobar *pBar;  //pBar is stored in stack

     pBar = new Foobar();  //the object is created in heap?  What part of the object is stored on heap

}

EDIT:
Что смущает меня, если pBar = new Foobar(); сохраняет объект в куче, почему int nLoc; и int pubVar;, которые являются компонентами объекта, хранящегося в стеке? Звучит противоречиво для меня. Разве время жизни pubvar и pBar не должно быть одинаковым?

Ответы [ 4 ]

10 голосов
/ 14 января 2011

Термины «куча» и «стек» являются устаревшими, неточными и запутанными терминами, относящимися к продолжительности хранения.

Объекты с «длительностью автоматического хранения» - это то, что глупые люди называют «объектами стека».Это те, которые вы определите внутри функции как «локальные переменные».Они выходят за рамки, когда заканчивается их вмещающий блок.

Объекты с «динамической длительностью хранения» - это те, которые вы создаете в free store с помощью ключевого слова new (или, если вы глупый, malloc), а затем уничтожьте, когда захотите, с ключевым словом delete (или, если вы глупый, free).

Есть также объекты с "статическая длительность хранения », на которые распространяются всевозможные причудливые правила порядка инициализации и тому подобное.Мы склонны не использовать их в идиоматическом C ++ настолько, насколько мы можем помочь.

Что касается конкретных переменных в вашем примере кода, все ваши комментарии точны, несмотря на ошибку в терминологии.

Приложение:

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

В наши дни это не всегда верно, и это, безусловно, не предписано стандартом C ++, который не заботится о том, где что хранится.Его волнует только то, как они созданы и уничтожены, и как долго они живут.

5 голосов
/ 14 января 2011

Я обновил ваши аннотации тем, что я считаю более правильным. Обратите внимание, что Томалак прав, что «стек» и «куча» не определены стандартом, и механизмы, отличные от стека, могут использоваться для передачи параметров для хранения автоматических переменных.

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

class Foobar
{
      int n; //Stored wherever the current object is stored
             //  (might be static memory, stack or heap depending 
             //  on how the object is allocated)

      public:

          int pubVar; //Stored wherever the current object is stored 
                      //  (might be static memory, stack or heap depending 
                      //  on how the object is allocated)

          void foo(int param)  //param stored in stack or register
          {
                int *pp = new int; //int is allocated on heap.
                n = param;
                static int nStat;  //Stored in static area of memory
                int nLoc;          //stored in stack or register
                string str = "mystring"; // `str` is stored in stack, however 
                                         //    the string object may also use heap 
                                         //    to manage its data
                ..
                if(CONDITION)
                {
                    static int nSIf; //stored in static area of memory
                    int loopvar;     //stored in stack or register
                    ..
                }
          }
}

int main(int)
{
     Foobar bar;    //bar stored in stack

     Foobar *pBar;  //pBar is stored in stack

     pBar = new Foobar();  //the object is created in heap.  
                           //   The non-static data members are stored in that
                           //   memory block.

}
1 голос
/ 14 января 2011

Я согласен с Томалаком,

C ++ не волнует, где хранятся вещи.Его волнует только то, как они построены и разрушены, и как долго они живут.

Как это происходит, определяется реализацией, компилятор может оптимизировать таким образом, что у вас ничего не будет храниться в «стеке», когда вы этого ожидаете.То, как происходит распределение в куче, определяется реализацией функции new / malloc или какой-либо третьей стороны (функция new может вызвать malloc).

Что наиболее вероятно произойдет в вашем примере, это:1010 *

Несколько вещей, которые могут вас удивить.Массив в стиле C, такой как int array[5], хранится не так, как int* pointer= new int[5], во втором случае, скорее всего, будет использоваться больше памяти, поскольку он хранит не только память для массива, но и память в стеке"для указателя.

Статические константы, такие как 5 и "cake", обычно хранятся в отдельном разделе .DATA исполняемого файла.

Важная вещь, которую нужно понять при использовании C ++, большинство из этих вещей определяются реализацией.

0 голосов
/ 14 января 2011

Нестатические члены данных находятся «внутри» каждого экземпляра этого класса: находится ли он в стеке, куче или где-либо еще - неизвестно, просто взглянув на член в определении класса. Нет смысла говорить о хранении нестатических элементов данных, не говоря о хранении экземпляра класса, к которому они принадлежат.

struct A {
  int n;  // you cannot say n is always on the stack, or always on the heap, etc.
};

int main() {
  A a;  // a is on the stack, so a.n is also on the stack
  A *p = new A();  // *p, which means the object pointed to by p, is on the heap,
                   // so p->n is also on the heap
                   // p itself is on the stack, just like a
  return 0;
}

A global;  // global is neither on the stack nor on the heap, so neither is global.n

«Стек» - это место, где находятся переменные, ограниченные временем жизни одного вызова функции; это также называется «длительностью автоматического хранения». Существуют различные стратегии выделения стеков, и, в частности, каждый поток имеет свой собственный стек, хотя тот, который является «стеком», должен быть понятен из контекста. С разделенными стеками происходят интересные вещи (которые позволяют расти и уменьшаться), но в этом случае это все еще один стек, разбитый на несколько частей.

«Куча» - всего лишь неправильное выражение в том смысле, что «кучи» относится к «основной» куче, используемой malloc и различными формами new; это также называется «динамическая продолжительность хранения».

Глобальные переменные, статические члены данных и статика на уровне функций не принадлежат ни стеку, ни куче; также называется «статическая продолжительность хранения».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...