unique_ptr reset problem



  • I have some problem with unique_ptr.reset(): when i pass a pointer to reset(so unique_ptr take ownership of it) it doesn't reset the source pointer. This cause the pointer to not be unique.

    std::unique_ptr<TestClass> ptr;
    TestClass *testClass= new TestClass ;
    ptr.reset(testClass);
     //testClass is still valid, should be nullptr now...
    

    from the <memory> header file reset() doesn't set nothing to nullptr



  • Hi,

    is not correct; in this case you set testClass as managed by ptr.
    You'll have testClass set to nullptr if you now do something like

    ptr.reset();
    

    or

    TestClass *newPointer = new TestClass;
    ptr.reset(newPointer);
    

    Read here for more info.



  • so how i can transfer ownership to unique_ptr?? basically what i want to achieve is to avoid to passing unique_ptr around, for example in a tree structure.



  • @ceora said:

    so how i can transfer ownership to unique_ptr??

    using unique_ptr::reset(newPointer) you pass the ownership to it.
    If you need to pass that pointer to functions or containers you could use std::shared_ptr



  • @ceora already answer you, I would add more details about it.

    The responsible of std::unique_ptr is help you manage the life time of the resource(I say resource, not memory because it can handle more than that).

    Basically, the api reset will reset the pointer hold by the unique_ptr
    Solution 1 :

    auto test_class = new TestClass;
    std::unique_ptr<TestClass> ptr(test_class ); //let the unique_ptr handle the resource--test_class
    ptr.reset(nullptr); //set the resource handle by the unique_ptr to nullptr
    

    Could we initialize the unique_ptr with better solution?Yes
    Solution 2 :

    std::unique_ptr<TestClass> ptr(new TestClass); 
    

    Is it possible to make it even better?Yes
    Solution 3 :

    auto ptr = std::make_unique<TestClass>(); //need c++14
    

    If you cannot wait until most of the compiler to support c++14, you can implement it by yourself

    template<typename T, typename... Args>
    std::unique_ptr<T> make_unique(Args&&... args)
    {
        return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
    }
    

    What are the benefits of using make_unique?

    1 : it makes your codes more compact
    2 : it helps you avoid the trap of "resource leak"

    suppose you have an api which accept std::unique_ptr<TestClass> as following

    void do_something(std::unique_ptr<TestClass> lhs, std::unique_ptr<TestClass> rhs)
    {
        //.........
    }
    

    If you call it like this

    do_something(std::unique_ptr<TestClass>(new TestClass), std::unique_ptr<TestClass>(new TestClass));
    

    The memory may leak if one of the construction fail(for details, please study effective c++ or effective modern c++)

    @If you need to pass that pointer to functions or containers you could use std::shared_ptr
    Not really, you can pass by pointer, pass by reference or move it.

    (1) pass by pointer

    void do_something(TestClass *ptr);
    

    (2) pass by reference

    void do_something(std::unique_ptr<TestClass> &ptr);
    

    (3) move it

    void do_something(std::unique_ptr<TestClass> ptr);
    

    you can move it as following

    auto ptr = std::make_unique<TestClass>();
    do_something(std::move(ptr));
    

    or

    do_something(std::make_unique<TestClass>());
    

    I prefer solution (1) since that api is more flexible(do not bound to particular smart pointer).
    Raw pointer is not ideal at resource management but very good at access resource

    In my humble opinion, the objective of std::shared_ptr is sharing the resource
    It is much harder to predict the life time of the shared_ptr, and it is also more expensive than
    the zero performance penalty unique_ptr.Besides, unique_ptr could show you that this is a unique resource



  • @stereomatchingkiss thanks for the explanation! How I can find out when using shared_ptr, unique_ptr or raw pointer, ore better when resource can be considered shared or as visitors (using the pointer, look at the data, ..)? if pointer are mostly used for data sharing(for allocation are better containers), when use unique_ptr instead of non pointer variable? Another problem is debugging smart pointer, they aren't deferenced making them hard to read..


  • Moderators

    @ceora

    shared_ptr::use_count() helps for knowning if there are other instances sharing this memory.
    The debugging of smart pointers may be an issue of the debugger used. The main problem, I see, is that there is an extra layer in between, which makes debugging less intuitive. However, this is the little pain you have to accept with the comfort and advantages of smartpointers. Besides the additional layer there is no other problem in debugging.



  • @ceora koahnig already answer your question

    How I can find out when using shared_ptr, unique_ptr or raw pointer
    Before I answered you this question, I would like to say the best way(maybe) is "do not use any pointer, put your resource on stack".

    Example:

    void MainWindow::closeEvent(QCloseEvent *event)
    {
        QSettings setting{"ThamSoftWare", "QRenamer"};
        setting.setValue("geometry", saveGeometry());
    
        event->accept();
    }
    

    Is easier to deal and more efficient than(because you save the cost of allocate memory on heap)

    void MainWindow::closeEvent(QCloseEvent *event)
    {
        auto setting = std::make_unique<QSettings>{"ThamSoftWare", "QRenamer"};
        setting->setValue("geometry", saveGeometry());
    
        event->accept();
    }
    

    If you just need a local object to do some job, rather than new it and put it into smart pointer, just create it on stack(someone call them auto object?).

    As far as I know, if you do not need to shared the resource, then you do not need the shared_ptr.You could think it like this way too, if stack work for you, do not use unique_ptr, if unique_ptr works for you, do not use shared_ptr, treat shared_ptr as the last resort.

    I never have any real life experience when shared_ptr is a much better solution than scope object on stack or unique_ptr, so the following example may look fake(pseudo codes).

    Assuming you are design a game, the game have a monster which could spawn themselves(slime)
    Even the slime can spawn, all of the slime share some common state(mp, hp or other's) and some
    different states.

    class slime_state
    {
        public:
       //......some states
    }
    
    class slime
    {
      public:
      //some operations
      private:
         std::shared_ptr<slime_state> states_;
    }
    

    In this kind of situation, you may want to create many slime with same states_ and do not want to bother to delete the slime_state when the last slime die. This maybe a good situation to give shared_ptr a try.

    For more details, you can study "The c++ programming language, 4th"

    Another problem is debugging smart pointer, they aren't deferenced making them hard to read..
    I seldom use the debug mode to debug, so I cannot give you much suggestion about that, sorry


  • Moderators

    @stereomatchingkiss
    shared_ptr are good when have a container holding the shared_ptr, but you need to update while the actual object is still in use.
    E.g. you change the properties of an object by placing a new pointer and removing the old one. When the object is still used somewhere, this routine can be completed without side effects. For such reasons I am using shared_ptr very often. In real-time apps the primary owner cannot always wait until the each subs are finished. Otherwise I would have to do all the book-keeping myself.

    I have never used a unique_ptr so far.

    At least on windows through Qt creator with MinGW the debugging has no major disadvantges besides the additional layer. IIRC also under Ubuntu it did work in the same manor.



  • @koahnig
    From what i heard from Herb Sutter conf, it's better to always use unique_ptr if you don't know if resource will be shared, cause shared_ptr are less efficient (because thy keep a reference count), also it's better to don't pass smart pointer around unless you want express the intention to pass ownership. My problem is that i want to optimize code before write it XD. However if i want go for sure i think i will always use shared_ptr too...

    For the debugging problem, is the additional layer that make hard to read for me, i would like to have data well presented so i can look fast at them, without expand too many tree elements in debug view.


  • Moderators

    @ceora
    However, that is exactly the place where I am using the shared_ptr. I have a central container holding information which is required by other parts of the SW. The information will change once in a while, but the already started calculations cannot be stopped, but have to be finished with the very same information in all places. Therefore, I could do only an update when all calculations have been done. However, this point I might have to start the next one already. Certainly I could do all this without using a standard shared_ptr, but at day's end I would probably add a similar and more time-consuming functionality.

    The additional layer is basically and two additonal clicks (IIRC) in the debug window. Makes tghe window a bit bigger, but that's it.

    Certainly shared_ptr are not a good solution everywhere. Because of overhead they should be used only where required.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.