473,405 Members | 2,445 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

have I wrong order in assignment operator and cpy-ctor

This class template and main works perfectly fine. But could be better.
I have this class template called Handle that has a pointer declared as T*
body;
As you can see I have a reference counter in the class template so I know
how many references I have to the body. In my case it's the Integer wrapper
class which is the body.
This template works for many different types.
The one that I use is named Integer and is a Wrapper for an int. The code
for this is not include
because it doesn't add any futher information.
At the bottom I have a main.
In main I can call the stand alone function addNodeToSTL plus many more to
add nodes to the STL list container named myList1.
Here is the stand-alone function that add nodes to the STL list container.
void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}

This handle_t is typedef to
typedef Handle<Integer> handle_t;

Now to my question.
In this class template Handle I have one assignment operator and one copy
constructor.
This code for assignement operator and cpy-ctor. I thing the order is wrong
I must have statement
ref_count = h.ref_count; after
(*h.ref_count)++;
Now it's before so that's wrong order.
It's the same order mistake in both assignment operator and the cpy-ctor.
Do you agree with me.?
Below can you find the complete class template Handle and some parts of
main.

Handle(const Handle& h) //copy constructor
{
body = h.body;
ref_count = h.ref_count;
(*ref_count)++;
}

const Handle& operator=(const Handle& h) //assignment operator
{
if (this != &h)
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(*h.ref_count)++;
}
return *this;
}

//Tony
template<class T>
class Handle
{
public:
Handle()
{
body = new T(0);
ref_count = new int(1);
}

Handle(T* body_ptr) //Constructor
{
body = body_ptr;
cout << "Body adressen = " << body << endl;
ref_count = new int(1);
}

~Handle() //Destructor
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
}

T operator*() const { return *body; }

T& operator*()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return *body;
}

T* operator->()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return body;
}

T* operator->() const { return body; }
bool operator==(const T& h) { return *body == h; }
bool operator==(const Handle& h) { return *body == *h.body; }

Handle(const Handle& h)
{
body = h.body;
ref_count = h.ref_count;
(*ref_count)++;
}

int getRefCount() { return *ref_count; }
void operator()(Handle& h) { cout << *h.body << endl; }

const Handle& operator=(const Handle& h)
{
if (this != &h)
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(*h.ref_count)++;
}
return *this;
}

private:
T* body;
int* ref_count;

void deleteAll()
{
delete body;
body = NULL;
delete ref_count;
ref_count = NULL;
}
};

void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}
typedef Handle<Integer> handle_t;

int main()
{
list<handle_t>* myList1 = new list<handle_t>;
list<handle_t>* myList2 = new list<handle_t>;
do
{
switch (huvudMeny())

{
case 0: return 0;
case 1: addNodeToSTL(myList1);
break;
case 2: displaySTL(myList1, myList2);
break;
case 3: deleteSelectedValue(myList1);
break;
case 4: deleteAll(myList1);
break;
case 5: findSelectedValue(myList1);
break;
case 6: testOperatorStar(myList1);
break;
case 7: testOperatorArrow(myList1);
break;
case 8: copyList(myList1, myList2);
break;
}
} while(1);
return 0;
}

//Many thanks

//Tony

Aug 21 '05 #1
1 1683
"Tony Johansson" <jo*****************@telia.com> wrote in message
news:5y*******************@newsb.telia.net...
: This class template and main works perfectly fine. But could be
better.
....
: Now to my question.
: In this class template Handle I have one assignment operator and one
copy
: constructor.
: This code for assignement operator and cpy-ctor. I thing the order
is wrong
: I must have statement
: ref_count = h.ref_count; after
: (*h.ref_count)++;
: Now it's before so that's wrong order.
: It's the same order mistake in both assignment operator and the
cpy-ctor.
: Do you agree with me.?
I do not think that this is a problem in this case. The
only thing to be aware of is that, in either case, the
behavior will be undefined in a multi-threaded program
(an atomic operation or a lock would be needed then).

: Below can you find the complete class template Handle and some parts
of
: main.
:
: Handle(const Handle& h) //copy constructor
: {
: body = h.body;
: ref_count = h.ref_count;
: (*ref_count)++;
: }
This is ok.

: const Handle& operator=(const Handle& h) //assignment operator
: {
: if (this != &h)
: {
: (*ref_count)--;
: if (!*ref_count)
: deleteAll();
: ref_count = h.ref_count;
: body = h.body;
: (*h.ref_count)++;
: }
: return *this;
: }
Ok as well. Note that the self-assignment test
becomes unnecessary if you order the operations
properly. The whole function can be written as:
++*h.ref_count;
if( 0 == --*ref_count ) deleteAll();
body = h.body;
ref_count = h.ref_count;

: //Tony
:
:
: template<class T>
: class Handle
: {
: public:
: Handle()
: {
: body = new T(0);
Note that whis will fail if T cannot be initialized
with 0 - making Handle less generic than needed.
You could write instead:
body = new T( T() ); // explicit call to dflt-ctr
// will initialize int and any
// built-in type to zero.

: ref_count = new int(1);
: }
:
: Handle(T* body_ptr) //Constructor
It is safer to make this constructor explicit:
explicit Handle(T* body_ptr)
(this will help avoid unexpected conversions).

: {
NB: it would probably be good practice to test
that body_ptr is not null (assert or throw), as
the rest of the code assumes/implies it never is.

: body = body_ptr;
: cout << "Body adressen = " << body << endl;
: ref_count = new int(1);
: }
:
: ~Handle() //Destructor
: {
: (*ref_count)--;
: if (!*ref_count)
: deleteAll();
: }
:
: T operator*() const { return *body; }
Usually the following function signature would
be used instead:
const T& operator*() const { return *body; }
If T is a complex class (as expected if a Handle
class is needed), this may avoid unnecessary
object copies.

: T& operator*()
: {
: if (*ref_count > 1)
: {
: (*ref_count)--;
: body = new T(*body);
: ref_count = new int(1);
: }
: return *body;
: }
Ok, so this implements copy-on-write (COW).
This has many caveats for the user, but
this function looks ok.

: T* operator->()
: {
: if (*ref_count > 1)
: {
: (*ref_count)--;
: body = new T(*body);
: ref_count = new int(1);
: }
: return body;
: }
:
: T* operator->() const { return body; }
The returned type should be const for consistency:
T const* operator() const { return body; }

: bool operator==(const T& h) { return *body == h; }
: bool operator==(const Handle& h) { return *body == *h.body; }
NB: these are best implemented as 'friend' operators. E.g.:
friend bool operator==(const Handle& a, const Handle& b)
{ return *a.body = *b.body; }
This ensures that x==y and y==x are always equivalent,
in particular if implicit conversions are involved.

: Handle(const Handle& h)
: {
: body = h.body;
: ref_count = h.ref_count;
: (*ref_count)++;
: }
:
: int getRefCount() { return *ref_count; }
This probably can be: ^const

: void operator()(Handle& h) { cout << *h.body << endl; }
Hum... unusual semantics.

: const Handle& operator=(const Handle& h)
: {
: if (this != &h)
: {
: (*ref_count)--;
: if (!*ref_count)
: deleteAll();
: ref_count = h.ref_count;
: body = h.body;
: (*h.ref_count)++;
: }
: return *this;
: }
:
: private:
: T* body;
: int* ref_count;
:
: void deleteAll()
: {
: delete body;
: body = NULL;
: delete ref_count;
: ref_count = NULL;
: }
: };
:
: void addNodeToSTL(list<handle_t>* myList)
NB: it would be more appropriate to use a reference:
void addNodeToSTL(list<handle_t>& myList)

: {
: handle_t myh(new Integer(getValue("Ange vardet som du vill lagga
in i
: listan/listorna: ")));
: myList->push_front(myh);
: }
: typedef Handle<Integer> handle_t;
:
: int main()
: {
: list<handle_t>* myList1 = new list<handle_t>;
: list<handle_t>* myList2 = new list<handle_t>;
: do
: {
: switch (huvudMeny())
:
: {
: case 0: return 0;
: case 1: addNodeToSTL(myList1);
: break;
: case 2: displaySTL(myList1, myList2);
: break;
: case 3: deleteSelectedValue(myList1);
: break;
: case 4: deleteAll(myList1);
: break;
: case 5: findSelectedValue(myList1);
: break;
: case 6: testOperatorStar(myList1);
: break;
: case 7: testOperatorArrow(myList1);
: break;
: case 8: copyList(myList1, myList2);
: break;
: }
: } while(1);
: return 0;
: }
:
: //Many thanks
:
: //Tony

I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- email contact
form
Brainbench MVP for C++ <> http://www.brainbench.com
Aug 22 '05 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Nitin Bhardwaj | last post by:
Thanx in advance for the response... I wanna enquire ( as it is asked many a times in Interviews that i face as an Engg PostGraduate ) about the overloading capability of the C++ Language. ...
9
by: Matthew Polder | last post by:
Hi, When a class Apple is written and the assignment operator is not explicitly declared, the operator Apple& operator=(const Apple&) is created by the compiler. Is there any difference...
13
by: Dan Tsafrir | last post by:
is the following code standard? (cleanly compiles under g++-4.0.2): struct Asc { bool operator()(int a, int b) {return a < b;} }; struct Des { bool operator()(int a, int b) {return b > a;} };...
3
by: Christian Christmann | last post by:
Hi, reading the output of gprof for one of my projects, I found that the STL list assignment operator consumes a larger fraction of the program's execution time. The exact entry in gprof's...
19
by: zzw8206262001 | last post by:
Hi,I find a way to make javescript more like c++ or pyhon There is the sample code: function Father(self) //every contructor may have "self" argument { self=self?self:this; ...
9
by: Matthias Pospiech | last post by:
I have a Class for complex operations: class CComplex { public: inline CComplex() { re=im=0.0; } inline CComplex operator*(CComplex c) { return CComplex(re*c.re-im*c.im,re*c.im+im*c.re);}...
15
by: Jeroen | last post by:
Hi all, I've got a very specific question about the evaluation order in C++. Assume some kind of custom array class, with an overloaded subscript operator. In the following code: { my_array...
20
by: TimeHorse | last post by:
I would like to gauge interest in the following proposal: Problem: Assignment statements cannot be used as expressions. Performing a list of mutually exclusive checks that require data...
9
by: George2 | last post by:
Hello everyone, I am wondering the default implementation of assignment operator (e.g. when we do not implement assignment operator in user defined class, what will be returned? temporary...
1
by: fabian.lim | last post by:
Hi all, Im having a problem with my code. Im programming a vector class, and am trying to overload the () operator in 2 different situations. The first situation is to assign values, e.g. Y =...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.