简体   繁体   中英

unique_ptr .release & .reset unexpected deleter behavior

I'm experimenting with smart pointers and experiencing a problem with the unique_ptr . What sparked this is that in VS2013 I am using .release() in a class destructor and it's not releasing (using TRACE ) yet it is with .reset . I have some sample code at the following URL: IDEOne Example Code

I've created a class containing two unique_ptr members. These members get assigned in the constructor and in theory, according to smart pointer theory as I understand it, should get delete d automatically. They are assigned a custom struct as a custom deleter, as defined below:

struct Deleter
    {
    void operator()(TCHAR* p) const
    {
        std::cout << "Deleter deleting .." << p << '\n';
        delete[] p;
    }
};

The unique_ptr members are declared as:

unique_ptr<TCHAR[], Deleter> szMySimpleString;
unique_ptr<TCHAR[], Deleter> szMySimpleStringLeak;

the unique_ptr members are then defined in the constructor of a class as:

    szMySimpleString = unique_ptr<TCHAR[], Deleter>(new TCHAR[255], Deleter());
    szMySimpleStringLeak = unique_ptr<TCHAR[], Deleter>(new TCHAR[255], Deleter());
    strcpy(this->szMySimpleString.get(), "szMySimpleString");
    strcpy(this->szMySimpleStringLeak.get(), "szMySimpleStringLeak");

When this class is deleted, I have the destructor running .release() in one example, .reset() in another. Each has behavior that I wouldn't expect. .release() is running the deleter on the wrong unique_ptr while .reset runs the deleter on both unique_ptr 's.

Please see the full code at the link at the beginning of this question (Note: There are 3 commented-out areas to run one at a time to see each effect).

If I run:

szMySimpleStringLeak.release();

I get the results:

    Doing Stuff ...
    Contents of szMySimpleString: szMySimpleString
    Contents of szMySimpleStringLeak: szMySimpleStringLeak

    MyStupidClass Destructor running...
    Deleter deleting ..szMySimpleString

If I run:

szMySimpleString.release();

I get the results:

Deleter deleting ..szMySimpleStringLeak

and if I run:

szMySimpleString.reset();

I get the results:

    MyStupidClass Destructor running...
    Deleter deleting ..szMySimpleString
    Deleter deleting ..szMySimpleStringLeak

I'd appreciate any input to why this behavior is unexpected (or rather why I should expect it).

Thanks!

unique_ptr::release relinquishes ownership of the managed object without destroying it. unique_ptr::reset will destroy the object using the supplied deleter.

It's not that calling release() is running the deleter on the wrong unique_ptr instance, but that it's not running the deleter on the instance on which you called release() . The deleter for the other instance is automatically called by the unique_ptr 's destructor, which is implicitly invoked by your class' destructor.

If you leave the unique_ptr instances alone, and called neither reset() nor release() on either of them, then you'll see the expected behavior when your class' destructor executes.

unique_ptr::release() does not delete the internal pointer, instead it releases the ownership of it. See the doc .

So in your case calling release() just causes memory leak.

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