question regarding the shared_ptr use_count

S

somenath

I am not able to understand the behavior of the following program

#include <iostream>
#include<memory>
#include<string>
using namespace std;

int main() {
auto p1 = make_shared<string> (10,'S');
cout<<"p1 use_count = "<<p1.use_count()<<endl;
shared_ptr<string> p2(new string()) ;
p1 = p2;
cout<<"p2 use_count = "<<p2.use_count()<<endl;
cout<<"second p1 use_count = "<<p1.use_count()<<endl;
return 0;
}
Output
++++++++++++++++
p1 use_count = 1
p2 use_count = 2
second p1 use_count = 2

I can understand the first two print. At beginning p1 points to one string so the reference count is 1.
When the statement p1=p2; executes p2's reference count gets incremented to 2 but at the same time I was expecting that p1's reference count to be decremented by 1 as p1 would be pointing to p2 now.
Please let me know where my understanding is going wrong?
 
I

Ian Collins

somenath said:
I am not able to understand the behavior of the following program

#include <iostream>
#include<memory>
#include<string>
using namespace std;

int main() {
auto p1 = make_shared<string> (10,'S');
cout<<"p1 use_count = "<<p1.use_count()<<endl;
shared_ptr<string> p2(new string()) ;
p1 = p2;
cout<<"p2 use_count = "<<p2.use_count()<<endl;
cout<<"second p1 use_count = "<<p1.use_count()<<endl;
return 0;
}
Output
++++++++++++++++
p1 use_count = 1
p2 use_count = 2
second p1 use_count = 2

I can understand the first two print. At beginning p1 points to one
string so the reference count is 1. When the statement p1=p2;
executes p2's reference count gets incremented to 2 but at the same
time I was expecting that p1's reference count to be decremented by 1
as p1 would be pointing to p2 now. Please let me know where my
understanding is going wrong?

p1 *is* p2. There are to references (p1 and p2) to the string initially
assigned to p1. Both have to go out of scope for the string to be deleted.
 
S

somenath

p1 *is* p2. There are to references (p1 and p2) to the string initially

assigned to p1. Both have to go out of scope for the string to be deleted.
I couldn't follow you. Why p2 would refer to the "string initially
assigned to p1"?
p2 is defined as follows

shared_ptr<string> p2(new string())
So according to my understanding p2 would refer to the empty string.
Then when the statement p1=p2; gets executed p1 also start referring to what ever p2 referring to. So the reference count of p2 will increase and also hoped that p1's reference count to be decremented by 1 but that does not happen.

I think this way because the book I refer for understanding these concept says.
"We can think of shared_ptr as if it has an associated counter,usually referred to as a reference count.
...
...
p=q p and q are shared_ptrs holding pointers that can be converted to one another. Decrements p's reference count and increments q's count; deletes p's existing memory if p's count goes to 0"

But I think it is better to think reference count as the count of pointers pointing to some memory location. In that case according to my program the following statement
p1=p2;
will increase the reference count of the memory location that p2 point as p1 also point to the same location.As p1 also point to the same meory location so when I print p1's reference count it prints the same count as p2.
cout<<"second p1 use_count = "<<p1.use_count()<<endl;
Please help me to get my understanding correct.
 
I

Ian Collins

I couldn't follow you. Why p2 would refer to the "string initially
assigned to p1"? p2 is defined as follows

*Please clean up the awful mess google makes of your quotes!*
shared_ptr<string> p2(new string()) So according to my understanding
p2 would refer to the empty string. Then when the statement p1=p2;
gets executed p1 also start referring to what ever p2 referring to.
So the reference count of p2 will increase and also hoped that p1's
reference count to be decremented by 1 but that does not happen.

I got p1 and p2 back to front, but the main point is still the same:
they both refer to the same object, so they must have the same reference
count.
I think this way because the book I refer for understanding these
concept says. "We can think of shared_ptr as if it has an associated
counter,usually referred to as a reference count. ... ... p=q p and
q are shared_ptrs holding pointers that can be converted to one
another. Decrements p's reference count and increments q's count;
deletes p's existing memory if p's count goes to 0"

This happens to p in the assignment operator, before the value pf q is
assigned to it.
But I think it is better to think reference count as the count of
pointers pointing to some memory location. In that case according to
my program the following statement p1=p2; will increase the
reference count of the memory location that p2 point as p1 also point
to the same location.As p1 also point to the same meory location so
when I print p1's reference count it prints the same count as p2.
cout<<"second p1 use_count = "<<p1.use_count()<<endl; Please help
me to get my understanding correct.

It does appear to be correct.
 
M

Marcel Müller

I couldn't follow you. Why p2 would refer to the "string initially
assigned to p1"?
p2 is defined as follows

shared_ptr<string> p2(new string())
So according to my understanding p2 would refer to the empty string.
Then when the statement p1=p2; gets executed p1 also start referring to what ever p2 referring to. So the reference count of p2 will increase and also hoped that p1's reference count to be decremented by 1 but that does not happen.

The reference counter is no property of the shared_ptr. It is a property
of the objects where the shared_ptr points to.
I think this way because the book I refer for understanding these concept says.
"We can think of shared_ptr as if it has an associated counter,usually referred to as a reference count.

shared_ptr instances do not have a reference counter.
p=q p and q are shared_ptrs holding pointers that can be converted to one another. Decrements p's reference count and increments q's count; deletes p's existing memory if p's count goes to 0"

The reference counter of *p and *q are modified. p and q do not have
reference counters.

But I think it is better to think reference count as the count of pointers pointing to some memory location. In that case according to my program the following statement
p1=p2;
will increase the reference count of the memory location that p2 point as p1 also point to the same location.As p1 also point to the same meory location so when I print p1's reference count it prints the same count as p2.

This is exactly what's going on.
cout<<"second p1 use_count ="<<p1.use_count()<<endl;
Please help me to get my understanding correct.

Internally shared_ptr uses helper objects to add the reference counter
to arbitrary objects. So your code effectively does the following:

auto p1 = make_shared<string> (10,'S');

tmp1 = new string#1(10,'S')
tmp2 = new helper_obj#1(1, tmp1)
p1 = shared_ptr(tmp2)

result:
p1 -> helper_obj#1{ counter = 1, content -> string#1{"SSSSSSSSSS"} }

cout<<"p1 use_count = "<<p1.use_count()<<endl;
shared_ptr<string> p2(new string()) ;

tmp1 = new string#2()
tmp2 = new helper_obj#2(1, tmp2)
p2 = shared_ptr(tmp2)

result:
p1 -> helper_obj#1{ counter = 1, content -> string#1{"SSSSSSSSSS"} }
p2 -> helper_obj#2{ counter = 1, content -> string#2{} }

p1 = p2;

++p2->counter
--p1->counter
because p1->counter goes to zero:
delete helper_obj#1
delete string#1

result:
p2 -> helper_obj#2{ counter = 2, content -> string#2{} }
p1 -> helper_obj#2{ counter = 2, content -> string#2{} }

cout<<"p2 use_count = "<<p2.use_count()<<endl;
cout<<"second p1 use_count = "<<p1.use_count()<<endl;


The helper objects cause additional allocations and more importantly an
additional indirection at every access to the stored strings. But they
are required to store arbitrary objects in shared_ptr instances.


Marcel
 
C

cuzdav

I am not able to understand the behavior of the following program

#include <iostream>
#include<memory>
#include<string>
using namespace std;

int main() {
auto p1 = make_shared<string> (10,'S');
cout<<"p1 use_count = "<<p1.use_count()<<endl;
shared_ptr<string> p2(new string()) ;
p1 = p2;
cout<<"p2 use_count = "<<p2.use_count()<<endl;
cout<<"second p1 use_count = "<<p1.use_count()<<endl;
return 0;
}

p1 use_count = 1
p2 use_count = 2
second p1 use_count = 2 <<< ??? ....
Please let me know where my understanding is going wrong?


Perhaps it useful to have it explicitly pointed out: the reference count is associated with the shared object, not with the shared pointers.

Initial:
p1 refers to object1, whose count==1
p2 refers to object2, whose count==1

Change p1 to refer to what p2 refers to

p1=p2

(Notice, when p1 changes what it points to, the refcount
goes down on the old object, and up on the new one. Afterall,
p1 no longer points to the old object so its refcount must
change!)

Result:
object1 destroyed (no references)
p2 still refers to object2, whose count==2
p1 also refers to object2, whose count==2


Notice that p1 and p2 both end up referring to the same underlying
object, so they both report the same reference count.


Chris
 
S

Stuart

Am 03.02.14 02:12, schrieb somenath:
I am not able to understand the behavior of the following program

#include <iostream>
#include<memory>
#include<string>
using namespace std;

int main() {
auto p1 = make_shared<string> (10,'S');
cout<<"p1 use_count = "<<p1.use_count()<<endl;
shared_ptr<string> p2(new string()) ;
p1 = p2;
cout<<"p2 use_count = "<<p2.use_count()<<endl;
cout<<"second p1 use_count = "<<p1.use_count()<<endl;
return 0;
}
Output
++++++++++++++++
p1 use_count = 1
p2 use_count = 2
second p1 use_count = 2

I can understand the first two print. At beginning p1 points to one string so the reference count is 1.
When the statement p1=p2; executes p2's reference count gets incremented to 2 but at the same time I was expecting that p1's reference count to be decremented by 1 as p1 would be pointing to p2 now.
Please let me know where my understanding is going wrong?

(this posting contains some ASCII art which will look quite bad if
viewed with proportional fonts).

The situation just before the assignment "p1 = p2;" looks like this:
Each shared_pointer does not point to the object directly but to an
intermediate object which contains the reference count. Both pointers p1
and p2 are the only shared_pointers pointing to their strings, so the
reference counts have both the value 1.


,''''''''`.
| refcnt 1|
,_______ `. | | _______________
| P1 |------=: |.......... . | |
L______| - | | `. |"SSSSSSSSSS" |
| ptr |----------'|_______________|
|_________J ,'
-'


,''''''''`.
| refcnt 1|
,_______ `. | | _______________
| P2 |------=: |.......... . | |
L______| - | | `. |"" |
| ptr |----------'|_______________|
|_________J ,'
-'


In the assignment statement, p1 will decrement the ref-count of the
intermediate object, since p1 no longer points to the intermediate
object of string "SSSSSSSSSS". Instead it will point to the intermediate
object of p2:


,''''''''`.
| refcnt 0|
,_______ | | _______________
| P1 | |.......... . | |
L______| | | `. |"SSSSSSSSSS" |
`. | ptr |----------'|_______________|
`. |_________J ,'
`. -'
\ |
`.|
---- ,''''''''`.
| refcnt 2|
,_______ `. | | _______________
| P2 |------=: |.......... . | |
L______| - | | `. |"" |
| ptr |----------'|_______________|
|_________J ,'
-'

Now the assigment statement will figure out that the reference count of
the intermediate object of "SSSSSSSSSS" has become zero, so it can
delete the intermediate object and the string "SSSSSSSSSS".

Sorry, if I did not use the proper vocabulary. The intermediate object
is an implementation details, although I doubt whether there is an
implementation that differs from this scheme.

Regards,
Stuart
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top