Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scoped_ptr ownership [duplicate]

Possible Duplicate:
What is a smart pointer and when should I use one?

I was reading an article and I found a small example to demonstrate the use of boost::scoped_ptr<T>:

#include <cstdlib>
#include <iostream>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

static int count = 0;

class printer
{
    int m_id;

public:
    printer(void) :
        m_id(count++)
    {
    }

    ~printer(void)
    {
        std::cout << "Printer " << m_id
                  << " destroyed" << std::endl;
    }
};

int
main(void)
{
    boost::scoped_ptr<printer> p1(new printer);
    boost::scoped_ptr<printer> p2(new printer);
    std::cout << "Exiting test program" << std::endl;

    return EXIT_SUCCESS;
}

The only thing I didnt understand in the article was this statement:

using scoped_ptr, you indicate that ownership transfer is not intended or allowed.

Maybe it was the wrong article to begin with as a beginner on this topic, but what exactly the above line means?

like image 920
SandBag_1996 Avatar asked Feb 02 '13 00:02

SandBag_1996


1 Answers

Most smart pointers have ownership of the object they are pointing to - they are in charge of destroying that object when the time comes. However, different smart pointers have different ownership semantics. That is, they tell the user of that smart pointer how the ownership may or may not be transferred, how it is shared amongst objects, when the object should be deleted, and so on. Using a certain smart pointer describes your intent with regards to the ownership of that object. Ownership can be transferred to other functions or objects.

boost::scoped_ptr has very strict ownership semantics. It doesn't allow any transfer of ownership at all. It achieves this by being non-copyable (so you can't pass it to another function by value).

As another example, a std::unique_ptr is also fairly strict. Its special ability is that it can be moved from. Passing an std::unique_ptr to a function as an rvalue will let that function steal ownership of the object. The original std::unique_ptr loses that ownership immediately. This ensures that ownership is only ever held by one std::unique_ptr.

The equivalent to boost::scoped_ptr in C++11 is a const std::unique_ptr. This is because making it const prevents any moving and thus ownership can not be transferred.

An easy way to see how important ownership semantics are is with an example. Let's say you're using an evil developer's library and it has a function that you don't know the implementation of, such as:

cat* foo();

You know this function returns a pointer to a cat. However, it's a raw pointer. You have no idea whether you should be destroying the cat (with delete) at some point or if the library will do it for you. You don't even know if the object was actually dynamically allocated. You have no idea if the library still keeps hold of the cat. In the past, if you had a function like this, you would need to look up the documentation to find out what to do. However, now that we have smart pointers in addition to raw pointers, raw pointers have their own ownership semantics - the most relaxed of them all. It says "You better trust me that I keep this cat valid for as long as you pass it around but I'll be the one managing it. Don't keep it for too long."

However, a wise and kind library developer would now write this function like so:

std::unique_ptr<cat> foo();

So how does this help? Well, the std::unique_ptr tells you a lot. It tells you that the function is giving up ownership of the cat object to you. The cat is now your sole responsibility. It's also very helpful in giving you a smart pointer because you don't need to think about deleteing it. You can just use the pointer and when it goes out of scope, the object will be destroyed. Or, if you want to, you can transfer ownership to another function.

This doesn't mean that only one pointer will ever have ownership of the cat though. As the proud new owner, it's up to you to decide what happens next. It's perfectly reasonable for you to decide that you want to start sharing ownership of your cat:

std::unique_ptr<cat> up = foo();
std::shared_ptr<cat> sp(up.release());

The wise and kind foo library developer only told you what her intentions were. She gave you the cat and now you're the owner. Now you can provide your own ownership semantics.

In this way, a boost::scoped_ptr is a bit like a greedy cat hoarder who will never share the cat with anybody, never give the cat to anybody, and will keep it until the day they die.

like image 190
Joseph Mansfield Avatar answered Oct 31 '22 18:10

Joseph Mansfield