Theo Buys Ответов: 1

Помещают ли функции-члены свои локальные данные в стек?


У меня есть простой вопрос о области действия объекта и области действия внутри функций-членов.

Компьютерная память, видимая для программы, в основном делится на две части:
1. стек
2. куча

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

Здесь у меня есть сфера применения:

{
  MyClassType *pObjOnHeap;
  {
     MyClassType objOnStack;
     objOnStack.sayHello();
   
     pObjOnHeap = new MyClassType;
     pObjOnHeap->sayHello();
  }
  delete pObjOnHeap;
}

То objOnStack создается его данные в стеке.
То pObjOnHeap создается его данные в куче.
Но обе их функции-члены толкают и выталкивают свои локальные данные в стек.
Это правильно?

Что я уже пробовал:

Я читал "язык программирования C++ 4-е издание" Бьярне Страуструпа.

1 Ответов

Рейтинг:
8

Richard MacCutchan

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

class CObject
{
public:
    void Method()
    {
        printf("\n\tIn Method\n");
        int localVar; // stack variable
        localVar = 5;
        printf("\t\tlocalVar: %p\n", &localVar);
        int* heapVar = new int[20]; // heap variable
        heapVar[1] = 100;
        printf("\t\theapVar: %p\n", heapVar);
        //delete[] heapVar; --> don't delete so next call to new will use new heap address
    }
};

int result = 0;
printf("result: %p\n", &result);
CObject localObject; // object on the stack
printf("\nlocalObject: %p\n", &localObject);
localObject.Method();

CObject* heapObject = new CObject(); // object on the heap
printf("\nheapObject: %p\n", heapObject);
heapObject->Method();

Вы должны увидеть разницу (в обоих случаях) между локальной переменной, созданной в Method, и переменная кучи.


Theo Buys

Таким образом, указатель heapVar находится в стеке, в то время как память для int[20] находится в куче. Указатель выходит из области видимости, но память остается. Я думаю, что это доказывает, что функции-члены выделенного объекта кучи не являются частью этого распределения, а только данными, а не локальными данными, используемыми в функциях-членах. Использование heapvar в этом примере-это своего рода Дикий Запад, а не часть данных класса. Таким образом, объект создает утечки памяти.

Richard MacCutchan

Да, я сделал это намеренно, чтобы показать, что второе выделение займет блок из другой части кучи. В то время как расположение стека используется повторно. Выбор использования стека или кучи действительно зависит от требований функции-члена. Приведенный выше пример просто используется для демонстрации разницы.

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

Theo Buys

Теперь забудьте о выделении объектов в функциях-членах. Давайте рассмотрим только переменные класса и вспомогательные функции-члены.

1) Если выделить объект класса в куче, то класс и его переменные находятся в куче, но если я запускаю функцию member, она использует стек для своих локальных переменных и только кучу для переменных класса.

2) Если создать объект класса в стеке, то класс и его переменные находятся в стеке, и если я запускаю функцию member, она использует стек как для своих локальных переменных, так и для переменных класса.

3) размер класса зависит от переменных класса, а не от размера кода memberfunctions.

Richard MacCutchan

1) Да.
2) Да.
3) Да.
Однако в 1 & 2 это объект и его переменные, которые выделяются в куче или стеке, а не в классе. И объект переменные; термин переменные класса относится к статическим переменным в определении класса.

Theo Buys

да, верно! Я должен сказать:
3) размер объекта класса зависит от переменных класса, а не от размера кода memberfunctions.

Richard MacCutchan

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

Theo Buys

Спасибо!