Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does the pointer exist even after the unique_ptr to which the pointer is assigned goes out of scope?

I recently started learning about smart pointers and move semantics in C++. But I can’t figure out why this code works. I have such code:

#include <iostream>
#include <memory>

using namespace std;

class Test
{
public:
    Test() 
    {
        cout << "Object created" << endl;
    }

    void testMethod()
    {
        cout << "Object existing" << endl;
    }

    ~Test() 
    {
        cout << "Object destroyed" << endl;
    }
};

int main(int argc, char *argv[])
{
    Test* testPtr = new Test{};
    {
        unique_ptr<Test> testSmartPtr(testPtr);
    }
    testPtr->testMethod();
    
    return 0;
}

My output is:

Object created
Object destroyed
Object existing

Why does row testPtr->testMethod() work? Doesn’t unique_ptr delete the pointer assigned to it on destruction if the pointer is an lvalue?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Edit: I learned from the comments that this method doesn’t check if the pointer exists. If so, is there a way to check if the pointer is valid?

Edit: I learned that I shouldn’t do anything with invalid pointers. Thank you for all your answers and comments.

>Solution :

You do not need a std::unique_ptr to write code with the same issue

int main(int argc, char *argv[])
{
    Test* testPtr = new Test{};
    delete testPtr;
    testPtr->testMethod();       // UNDEFINED !!!
    return 0;
}

The output is the same as yours here https://godbolt.org/z/8bocKGj1M, but it could be something else entirely. The code has undefined behavior. You shall not dereference an invalid pointer.

If you had actually used members of the object in testMethod() some faulty output or a crash is more likely, but also not guaranteed. Looking ok is the worst incarnation of undefined behavior.

You code demonstrates nicely why you should ban raw new completely. At least you should call new only as parameter to the smart pointers constructor, or even better, use std::make_unique. Its basically just a wrapper around new and a constructor call and its main purpose is to let you write code that is free of new:

int main(int argc, char *argv[])
{
    auto testPtr = std::make_unique<Test>();
    testPtr->testMethod();    
    return 0;
}

Even then you can access the raw pointer and do wrong stuff. Smart pointers help with ownership, but they are not fool-proof.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading