2

I have created an object of a class inside a function. The created object is passed as a parameter to another class. I expect that when I exit the function in which the object is created, the object must be destroyed.

Also any references to this object must be invalid, but I find that the object referenced after exiting the function is still valid. Trying to understand the scope of the object. The code snipped is given below.

class TextWidget
{
    public:
        TextWidget()
        {
            cout <<  "Constructor TextWidget" << endl;
        }

        TextWidget(int id)
        {
            _ID = id;
            cout <<  "Constructor TextWidget" << endl;
        }

        ~TextWidget()
        {
            cout <<  "Destructor TextWidget" << endl;
        }

        void printWidgetInstance()
        {
            cout << this << endl;
        }
        int _ID;
};

class AnotherWidget
{
    public:
        AnotherWidget()
        {
            cout << "Constructor AnotherWidget" << endl;
        }

        ~AnotherWidget()
        {
            cout << "Destructor AnotherWidget" << endl;
        }

        TextWidget* getTextWidget()
        {
            return _textWidget;
        }

        void setTextWidget(TextWidget* t)
        {
            _textWidget = t;
        }

        int getTextID() { return _textWidget->_ID; }

    private:
        TextWidget* _textWidget;
};


ButtonWidget b;
AnotherWidget a;

void fun()
{
    TextWidget t(7);
    b.setTextWidget(&t);
    a.setTextWidget(&t);
    a.getTextWidget()->printWidgetInstance();
    b.getTextWidget()->printWidgetInstance();
}

int main()
{
    fun();
    cout << "TextWidget in AnotherWidget is ";
    a.getTextWidget()->printWidgetInstance();
    cout << "Text ID in a is " << a.getTextID() << endl;
    getchar();
    return 0;
}

OUTPUT

Constructor AnotherWidget
Constructor TextWidget
Before deleting TextWidget in class ButtonWidget 0x73fdf0
Before deleting TextWidget in class AnotherWidget 0x73fdf0
0x73fdf0
0x73fdf0
Destructor TextWidget
TextWidget in AnotherWidget is 0x73fdf0
Text ID in a is 7
HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
SuryaRao
  • 51
  • 1
  • 6
  • Regarding `_ID` C++ has a lot of rules to handle a lot of interesting cases that no one ever tells you about before it's too late. In this case [you just broke one](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier) and are exposed to collisions with identical identifiers in the Standard Library implementation. Probably get away with it, but why risk it? – user4581301 Mar 29 '17 at 00:22

2 Answers2

4

A variable declared using automatic storage duration (not using new) has a lifetime of its scope. Accessing the variable outside the scope results in undefined behavior.

JGroven
  • 613
  • 1
  • 9
  • 14
  • In the above case there is no undefined behavior.. Everytime I get the same result. – SuryaRao Mar 28 '17 at 22:50
  • 3
    It is undefined behavior. Your compiler handles this issue just fine, but others will not. – JGroven Mar 28 '17 at 22:51
  • I tried in qt and codeblocks. Both give the same result. Did u get a chance to run it at ur side? – SuryaRao Mar 28 '17 at 22:53
  • @sandy47rao, how are you compiling? Try adding the flags -Wall -Werror -pedantic to the compilation command. – JGroven Mar 28 '17 at 22:56
  • 1
    It's undefined because the memory holding the object has been de-allocated. So it's free for any other object to overwrite the data. Basically, any small change and you suddenly have an "unexplained" bug cropping up somewhere else, because something else decided to store data where your object was "supposed" to be. – Jason Lang Mar 28 '17 at 23:06
  • @sandy47rao Just because it works in this case doesn't mean it will always work. If you add another function that allocates a different object, and call it right after calling `fun()`, I suspect you'll start to see strange behavior when you try to access the `TextWidget`. The reason is because it will be overwritten by subsequent function calls. – greyfade Mar 28 '17 at 23:06
  • it's like putting your furniture out in the street and still expecting to use it. Sure it saves room in your house and works for a while ... but are you going to bet on the TV and DVD player staying exactly where you put them? – Jason Lang Mar 28 '17 at 23:08
  • Even though the destructor of TextWidget is called, the value is retained in other classes. – SuryaRao Mar 28 '17 at 23:13
  • 1
    ***qt and codeblocks. Both give the same result.*** Neither of these are compilers, however you probably used mingw in both cases. – drescherjm Mar 28 '17 at 23:15
  • 2
    @sandy47rao "the value appears to be retained" is one possible effect of undefined behaviour. So you cannot say "there is no undefined behaviour" just based on program output. – M.M Mar 29 '17 at 02:49
1

You need to understand what classes, objects, pointers and references are. Classes are code in memory, this code deals with the member variables. A class does not occupy any data memory. When you create a object you instantiate the class. This step will reserve some data memory for the local data of one object instance of the class. To access this instance you get a reference to the object (this). An object variable holds a pointer to the data memory of an instance of a class.

When an object gets destroyed the occupied memory block gets listed as free but not cleared. So if you still have a reference to that memory block you may access it. And as long as the system doesnt use this memory block for other purposes you still will find your bits and bytes there.

You may declare some variables:

long      long_array[10];
myclass   myobject;

These variables are stored sequential in one memory block. When you now access the memory behind the long_array through that array:

long_array[10] = 12345; // valid range is from long_array[0] to long_array[9]

Than you will overwrite the data of the object myobject.

cmks
  • 527
  • 2
  • 11