PDA

View Full Version : Basic C++ doubt



munna
30th November 2006, 07:00
Hi,

Can some one please explain the function FredPtr& operator= (const FredPtr& p) int the following lines of code ?




class FredPtr;

class Fred {
public:
Fred() : count_(0) /*...*/ { } // All ctors set count_ to 0 !
...
private:
friend class FredPtr; // A friend class
unsigned count_;
// count_ must be initialized to 0 by all constructors
// count_ is the number of FredPtr objects that point at this
};

class FredPtr {
public:
Fred* operator-> () { return p_; }
Fred& operator* () { return *p_; }
FredPtr(Fred* p) : p_(p) { ++p_->count_; } // p must not be NULL
~FredPtr() { if (--p_->count_ == 0) delete p_; }
FredPtr(const FredPtr& p) : p_(p.p_) { ++p_->count_; }
FredPtr& operator= (const FredPtr& p)
{ // DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
// (This order properly handles self-assignment)
// (This order also properly handles recursion, e.g., if a Fred contains FredPtrs)
Fred* const old = p_;//const pointer to a const Fred
p_ = p.p_;
++p_->count_;

//Will -- operator not change the count ? But Fred is const ???
if (--old->count_ == 0) delete old;
return *this;
}
private:
Fred* p_; // p_ is never NULL
};



Thanks a lot.

e8johan
30th November 2006, 07:33
If several FredPtr (Fred pointers) point to the same Fred object, a reference counter in the Fred object is increased. If the FredPtr pointed at another Fred object that object's count is decreased (as the pointer stops pointing to it, it has one less reference). If this was the last pointer pointing to it, it is deleted.

This provides some sort of automatic memory management as long as FredPtr is used instead of Fred*.

sunil.thaha
30th November 2006, 09:07
This Qt Article will help you understand better -the reference counting concept

http://doc.trolltech.com/qq/qq02-data-sharing-with-class.html

munna
30th November 2006, 12:37
Yes, I understand the functionality. But I did not understand the function
FredPtr& operator= (const FredPtr& p)

and why the code should be written in that particular order ?

Thanks a lot for explaining

munna
30th November 2006, 14:14
Can someone please explain ? I'll really be greatful to them.

Thanks a lot for your time.

wysota
30th November 2006, 15:01
Fred* const old = p_;
This creates a temporary pointer pointing to the old data pointer of the object.


p_ = p.p_;
This assigns a new pointer to the object (note that if p==this, it assigns a pointer which is already there).


++p_->count_;
This increases the reference count for the current (new) object data.


if (--old->count_ == 0) delete old;
This decreases the reference count for the old pointer.

The order (of the last two statements) is very important, let's see what happens if you change it and try to do:

FredPtr p1;
p1 = p1;



Fred* const old = p_;
p_ = p.p_;
if (--old->count_ == 0) delete old;
++p_->count_;
1. You create the "old" pointer pointing to p1.p_
2. You assign p1.p_ to p1.p_
3. You decrease the reference count of p1.p_. Now if the reference count prior to performing that operation was "1", it will now be decreased and the pointer will be freed and you'll lose your data.
4. The pointer count will try to be increased, but the pointer is already invalid as you just deleted it and you get a pretty segfault.

If you first increase and then decrease the reference count, you make sure that the ref count of the object assigned to the current object will never reach 0 and will not cause the pointer to be deleted by accident.

munna
30th November 2006, 15:22
It might be a very silly doubt, but please bear with me.

Now let us consider the following code.




class Fred {
public:
static FredPtr create();
static FredPtr create(int i, int j);
...
private:
Fred();
Fred(int i, int j);
...
};

class FredPtr { /* ... */ };//the code above.

inline FredPtr Fred::create() { return new Fred(); }//Isn't the return type wrong ?
inline FredPtr Fred::create(int i, int j) { return new Fred(i,j); }



and the code here




FredPtr ptr1(Fred::create());
FredPtr ptr2 = ptr1;//What will happen here ?



Can you please explain how count will change in this case ?

Another doubt

Fred* const old = p_; means old is a const pointer to a const Fred. Then how can it be changed in the statement "if (--old->count_ == 0)" ?

Thanks a lot.

jacek
30th November 2006, 21:36
inline FredPtr Fred::create() { return new Fred(); }//Isn't the return type wrong ?
No, because there's FredPtr::FredPtr(Fred* p) constructor[1] that will be used to convert Fred* to FredPtr.


FredPtr ptr1(Fred::create());
FredPtr ptr2 = ptr1;//What will happen here ?
Both FredPtrs will point to the same Fred object and the reference count will be 2.


Fred* const old = p_; means old is a const pointer to a const Fred.
No, it's a constant pointer to a non-constant object.

[1] and it doesn't have "explicit" keyword in front of it.

wysota
30th November 2006, 21:54
I think it's also worth to note that in this situation:

FredPtr ptr2 = ptr1;
the compiler will use a copy constructor (line 20 of the listing in the first post) and not the assignment operator (lines 21-32 of the same listing).