Confused about link counting

Thanks for the help in advance. I am reading Scott Meyers' book, More Effective C ++, but one simple program in paragraph 29, Link Counting, really confuses me. The program is copied here:

String::String(const String& rhs): value(rhs.value) { ++value->refCount; }

Then the code:

 String s1("More Effective C++"); String s2=s1; 

I'm really confused why s1 and s2 will both have refCount 2. I understand that since the copy constructor is pass-by-reference-to-const, after s2 = s1, s2.refCount will become 2, and s1.refCount will not change at all . Please correct me! Thanks again.

Best wishes.

+4
source share
5 answers

value in this case is a pointer, and const -ness does not apply to the object it points to, so refCount is changed here.

Counting reference points is to share the same representation of an object without re-creating it until all links disappear, i.e. the number of links drops to zero. At this point, the view is de-distributed.

This works great for read-only objects, so if one of the referenced instances wants to change this general view, it is usually cloned, and recounting starts once.

Then, problems arise in making the reference count thread safe. Sutter wrote a lot about this, see gotw # 43 , gotw # 44, and gotw # 45 .

+3
source

I understand that s2.refCount will become 2, and s1.refCount will not change at all.

There is your misunderstanding. There is no animal like s2.refCount and s1.refCount . Rather, the variables are called s2.value->refCount and s1.value->refCount . Note that s2.value == s1.value , so they essentially use the same refCount element.

+3
source

If the reference count used by s1 is 1, then it will destroy the line with it when it died. Consider the following:

 String s2; { String s1("More Effective C++"); s2 = s1; } // A 

At point A, s1 dies. If its refcount is 1, it will clear the storage that it shares with s2 , and s2 will use invalid storage.

The reference count is not associated with each object. As you can see from the example I gave, this would be useless, because the reference counter would never be trustworthy as an indicator that can be safely cleared.

The reference counter is associated with pieces of storage for these objects. For both s1 and s2 there is only one reference counter. They have part of the repository with "More Effective C ++". This means that there are two links to this part of the repository. Each of the two should know that there are two of them, so that they do not clear the memory that the other uses.

+1
source

The reference counter must be in a separate shared memory:

 struct Foo { unsigned int * refcount; // shared among all "equal" objects! Foo() : refcount(new auto {1U}) { } Foo(Foo const & rhs) : refcount(rhs.refcount) { ++*refcount; } ~Foo() { --*refcount; if (*refcount == 0) { delete refcount; } } Foo & operator=(Foo const & rhs) { if (this == std::addressof(rhs)) { return *this; } --*refcount; if (*refcount == 0) { delete refcount; } refcount = rhs.refcount; ++*refcount; return *this; } // etc. }; 
0
source

value is a pointer to the main implementation structure. The string copy constructor copies the pointer to the new object ( s2 ) and increments the reference counter to the specified implementation structure. However, remember that the source object ( s1 ) has the same pointer, so the reference count, as seen from s1, will also be increased. There is only one basic implementation structure, so acting on it from a single String object affects all other String objects that share this implementation structure. This is the whole point of reference counting!

0
source

All Articles