views:

77

answers:

3

Does the following code mean that when this function returns, the request object inside this class still holds a reference to this object?

boost::shared_ptr<Request> RequestList::GetRequest()
{
    boost::mutex::scoped_lock(listmtx);
    request = boost::shared_ptr<Request>(new Request());
    return request;
}

used:

request = requests->GetRequest();  //Ref count is two on request object when it returns??

even after having completed above assignment, we still have a ref count of two on request...

where requests is just a RequestList pointer (raw pointer)...

+1  A: 

It's two on return, one at the end of the statement.

request = boost::shared_ptr<Request>(new Request()); // ref count = 1
return request; // makes a copy of request. ref count = 2

So when it returns it's 2 because there is a temporary.

request = requests->GetRequest(); // it's two because there is still a temporary
// at the end of the statement all the temporaries are destroyed,
// ref count decremented to 1

Of course you can use request.use_count() to get the reference count.

ybungalobill
This was my initial thought, but the temporary is destroyed *before* the function returns (at the end of the full-expression of the return statement). Anyway, unless he's compiling with `-O0`, copy elision prevents that from happening at all.
Potatoswatter
@Potatoswatter: What temporary??? We are talking about the temporary at the assignment statement outside GetRequest.
ybungalobill
ref count does not go to one after finishing assignment statement...
Tony
Ah, right. There is another temporary at the `return` statement, although it's optional. It is the same as the return value… actually I was backwards before, the named returned object is destroyed before return, not the temporary. Anyway I forgot that copy elision doesn't apply in the caller as well unless the function is called from a declaration, not an assignment. You might note that `boost::shared_ptr<Request> request = requests->GetRequest();` is likely to produce no temporaries. +1
Potatoswatter
@Tony, then your code is not complete to answer you question. Where the second code block is written?
ybungalobill
The reference count is two because you end up with two pointers after all the temporaries are destroyed. `request` is not declared inside `GetRequest()`, so it must have a wider scope.
Mike Seymour
@ybungalobill: it is inside the thread that produces these request objects...
Tony
@Tony: this is not so informative. Is request is an alias to requests->request? If not then you really have *two* different pointers to the same object.
ybungalobill
I think it prob should be last_request, (as sb else already suggested) instead of just request, cause an alias wouldn't really make sense as I'd need a different pointer for every object inside the requests list...
Tony
+1  A: 

The reference count is equal to the number of shared pointers in existence. In this case, it looks like, after creating the shared pointer, you end up with two copies (the assignment to request inside GetRequest(), which I'm guessing is a member of RequestList, and the assignment to request of the result of GetRequest()).

If both of these are shared pointers, and they don't both refer to the same pointer, then you will end up with two copies of the original pointer, and hence a reference count of two.

Mike Seymour
How do I get them to refer to the same pointer?? Sorry for sounding dumb, but this whole reference count idea is not entirely clear to me yet...
Tony
I'm pretty sure you don't want them to refer to the same pointer; I was just stating my assumption that they don't. Basically, everything that needs the request to exist should have a shared pointer, and it will exist for as long as any of the pointers do. In your code, the list is keeping hold of a shared pointer, as well as giving one to whatever called `GetRequest`, so ownership is shared between both objects. If you just want the list to hand out a request and not worry about deleting it, then don't keep a shared pointer in the list.
Mike Seymour
+3  A: 

request is a private class variable...

Then there are two shared_ptr objects with a handle to the new Request(): the one in the calling function and the private class variable. Both legitimately bump the refcount.

Unless there's a reason for the private class variable to exist, eliminate it. At the very least, rename it last_request, because that's what it really is.

(Of course, when last_request gets reassigned by another call to GetRequest, its handle to the previous request goes away.)

Potatoswatter