Search code examples
c++operator-overloadingassignment-operator

Destructor of struct called before assignment operator


I have a struct, Foo, with a pointer array of Bar.

struct Foo
{
    Bar* _BarList;

    Foo()
    {
        _BarList = new Bar[1];
        _BarList[0] = Bar(10, 20);
    }

    Foo& operator=(const Foo& foo)
    {
        Bar* tmpBarList = new Bar[1];

        tmpBarList[0] = foo._BarList[0];

        delete[] _BarList;

        _BarList = tmpBarList;

        return *this;
    }

    ~Foo()
    {
        delete[] _BarList;
    }
};

I call it like this

Foo baz = fooFunc();

(It seems) that if I create an instance of Foo (f) inside a function (fooFunc) and return it, the destructor is called before the value is returned as I lose the contents of _BarList.

This makes sense as it was created within the function. Here is an example.

Foo fooFunc()
{
    Foo f = Foo();
    return f;
}

If I return an instance of Foo directly on the return, the destructor of that item isn't called until after the equals operator has been called (by the equals statement on the line of the call).

Foo fooFunc()
{
    return Foo();
}

I suppose this makes sense as I am creating Foo inside the object, and things are cleared up before the object is returned.

I think I can resolve this by doing the return like this (after writing a new constructor to take Foo):

Foo fooFunc()
{
    Foo f = Foo();
    return Foo(f);
}

1) Am I right in my assumptions?

2) Is there another way to do it that would not require so many repeated assignment operators being called?

Edit: Please consider that this function would normally do a lot more than just return Foo()!


Solution

  • I think the different behaviours you're experiencing are due to compiler optimization.

    In any case,

    Foo baz = fooFunc();
    

    needs a copy constructor to work, because it will construct a new object from fooFunc's returned one.

    For instance

    Foo(const Foo& foo) : _BarList( NULL )
    {
        ::operator=( foo );
    }
    

    This will guarantee fooFunc() return object is copied to the locally declared Foo baz object.

    Note: Actually, calling operator= from copy constructor is a bad practice (but I mentioned it here to give you a quick answer and it will work in your case). Check this post: Copy constructor and = operator overload in C++: is a common function possible?