简体   繁体   中英

Returning Obj& in C++, what happens to the temp pointer?

Class

class Dummy
{
public:
    int x;

    Dummy(int y):x(y)
    {
    }

    ~Dummy()
    {
        std::cout<<"boom"<<std::endl;
    }
};

Function

Dummy& getRef()
{
    Dummy* temp = new Dummy(5);
    return *temp;
}

Call

Dummy* get = &getRef();
std::cout<<get->x<<std::endl;
get->~Dummy();

My intention was to get a dynamic object instance from a function and then pass it into a pointer at main.

My question:

After calling get->~Dummy(); , is the pointer Dummy* temp still alive or dangling?

I know that objects that are dynamically created won't get destroyed unless the destructor is called(even if it goes outside the scope) but i am not sure about the pointer itself.

The issue can be easily overcome by using unique_ptr but i want to know more about lifecycles.

I know that objects that are dynamically created won't get destroyed unless the destructor is called.

That isn't accurate . Destructors fire when an object is being destroyed unless someone has solid reason to manually fire them (and you don't here). They don't instigate that destruction. Something else does (whatever kicked off the object destruction, be it scope-exit, a delete , etc).

And yes, you're leaking memory. You have a new without a corresponding delete . There is the very soul of a memory leak. If you lose the manual destructor invoke and use

delete get;

your code will be sound (though odd, none-the-less).

A pointer is just a location in memory. When your function getRef() exits the temp variable is gone, but that allocation is still present.

You can still get the address from the return variable.

delete get;

will destroy your object

If the calling code doesn't delete that object you have a memory leak.

Explicitly calling destructors is generally not wise. Some instances like scripting languages require this kinda of thing but its rare.

You allocated memory with new , so the memory is only released when you delete it (which you do not do). The destructor of the pointee object doesn't deallocate anything.

You explicitly call the destructor of the pointee object, so it is "destroyed" but not deallocated. If you then delete the pointer, the destructor will have been called twice, which you do not want.

Only explicitly call a destructor when you intend to use placement new to construct a new object in the memory it formerly occupied. After explicitly calling the destructor ( get->~Dummy() ) the pointer still points to a valid memory location, albeit without a constructed object at that location.

What really happens in your example (though you SHOULD NOT write this kind of code):

  • within getRef() (line with new Dummy(5)), allocation happens, AND constructor is called within allocated space

  • until get->~Dummy() no changes are made; it seems (though here I'm not exactly 100% sure) that all the conversions from pointers to references and back are irrelevant and don't cause any constructors to be called (in any case, you shouldn't do these kind of things, at least for readability)

  • when get->~Dummy() is called, it calls destructor, but doesn't deallocate underlying memory block. After this point, you can call "placement new" with your 'get' pointer, creating a different object within the same allocated space (and having the same memory address), or you can deallocate memory block (using whatever-your-library-new-uses-for-allocation), or you will have a memory leak (as PhilCK has noted).

As a rule of thumb, you SHOULD NOT call destructors explicitly for objects you've created via 'new', as it has quite special meaning (see above); use 'delete' instead ('delete' will both call destructor and deallocate underlying memory block).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM