out0FBox Ответов: 1

Что такое фрейм стека, когда два объекта одного класса работают с одной и той же переменной-членом?


У меня есть несколько вопросов по приведенному ниже примеру кода :

#include <iostream>

using namespace std;

class Example
{
    int a;
    public:
    void setval(int x);
 
    int addval(Example &ex);
};

void Example::setval(int x)
{
    a=x;
}


int Example::addval(Example &ex)
{
    int c;
    c=ex.a+a;
    return c;
}

int main()
{
    Example obj1,obj2;
    int sum;
    obj1.setval(10);
    obj2.setval(20);
    sum=obj1.addval(obj2);
    cout<<" the sum is :"<<sum<<endl;
}

Output :
$g++ -o main *.cpp
$main
 the sum is :30

Вопросы:
1> Когда выполняется строка sum=obj1.addval(obj2);, как выглядит стек функций?
1.a> При вызове addval(obj2) с помощью obj1 содержит ли стек obj1.addval адрес памяти переменной obj2.a ?

2> какова область действия переменной c ?

3> является ли c переменной-членом ?

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

Если я не смог четко сформулировать свой вопрос, пожалуйста, скажите об этом.
Заранее благодарю вас за ваши ответы.
С уважением!

Gerry Schmitz

Это не "нормальные" вопросы для "новичка". К чему ты клонишь? Это что, домашнее задание?

out0FBox

Просто программист на Си, пробирающийся в ООП. Интересуюсь внутренней работой.

out0FBox

Я предполагаю, что объекты имеют собственный стек, где у них есть копия членов класса, так же как функции имеют собственный стек, содержащий локальные переменные.
Если объекты хранятся в куче, мне придется пересмотреть вопрос. Любые предложения помогут.

1 Ответов

Рейтинг:
5

Rick York

Во - первых, я рекомендую тщательно изучить отладчик вашего компилятора. Вы можете узнать довольно много об этом материале, пройдя один шаг через некоторый код и посмотрев на содержимое регистров процессора и дисплеев необработанной памяти. Если у вас его нет, Visual Studio 2017 доступна бесплатно в версии Community Edition. Он у меня есть, и я им пользуюсь, и это очень хорошо.

1. I'm not sure what you mean by "function stack". The processor has a stack and return addresses are pushed on it when functions are called and they are popped when returning from the function. From the return address, the debugger can discern a call stack which is a list of which function has called which. Keep in mind that when functions are called the compiler will know which CPU registers will be affected and it pushes those on the stack at call time and pops them off and restores them at return. You can see the instructions that do this by looking at assembly language listings that can be generated by the compiler. That can be instructive.

При вызове addval компилятор будет помещать указатель this вызывающего объекта Example и ссылку ex в стек. Он также передает обратный адрес вызывающего абонента и содержимое любых регистров, которые будут затронуты.

1А. Нет. Этот указатель obj2 выталкивается, а ее " а " - члены будут быть смещение от этого.

2. c является локальным для метода addval. Когда выполнение возвращается из addval c, оно выходит за пределы области видимости, поэтому оно будет уничтожено. Для целого числа, которое не делает ничего, кроме объектов, будут вызваны их деструкторы, чтобы освободить любые выделенные ресурсы.

3. нет, c является локальным для метода addval.

Что касается вашего другого вопроса, то нет, объекты не имеют своего собственного стека. Когда объект создается либо в стеке, либо в куче, память выделяется для его элементов данных. Функции также не имеют собственного стека. У них есть то, что называется кадром стека, который в основном является базовым регистром, который содержит адрес (указатель стека при вызове функции), а локальные переменные являются смещениями от него. Опять же, вы должны посмотреть на некоторые списки сборок, чтобы увидеть, как это работает. Вы увидите, как адреса передаваемых аргументов смещаются в одном направлении от базы стека, а локальные переменные смещаются в другом направлении.


out0FBox

Огромное спасибо за объяснение, Рик. Я попробую ваш подход, когда буду отлаживать.

С уважением!!