473,614 Members | 2,351 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Assignment operator self-assignment check

Is there ever a reason to declare this as

if(*this == rhs)

as opposed to what I normally see

if(this == &rhs)

?

Seems like the former version is going to be more expensive rather than
simply comparing addresses as in the latter (plus the former requires
the class to define operator== as well, no?). Wondering if that added
effort is ever justified.

Sep 20 '06 #1
34 7155
Chris wrote:
Is there ever a reason to declare this as

if(*this == rhs)

as opposed to what I normally see

if(this == &rhs)

?
The self-assignment check detects object identity, which C++ specifies as an
object's addresses.

The degenerate situation of copying a value into an object which already had
that value is less important. Just let it happen; don't always waste CPU
cycles checking for it.

--
Phlip
http://www.greencheese.us/ZeekLand <-- NOT a blog!!!
Sep 20 '06 #2
Chris wrote:
Is there ever a reason to declare this as

if(*this == rhs)

as opposed to what I normally see

if(this == &rhs)

?

Seems like the former version is going to be more expensive rather than
simply comparing addresses as in the latter (plus the former requires
the class to define operator== as well, no?). Wondering if that added
effort is ever justified.
Well, as long as we're dealing with hypotheticals: If (1) checking the
class for equality is cheap, (2) checking for equality frequently
evaluates to true even though it's not the same object (in the sense of
occuping the same address), and (3) using the copy constructor is very
expensive, then one can imagine using the former version, since it will
avoid unnecessary copy constructions.

The latter version ought to be the default, though.

Best regards,

Tom

Sep 20 '06 #3
Chris posted:
Is there ever a reason to declare this as

if(*this == rhs)

That is not a declaration -- choose your words carefully.

as opposed to what I normally see

if(this == &rhs)

The latter compares the ADDRESSES of two objects, while the former compares
the two objects themselves.

Seems like the former version is going to be more expensive rather than
simply comparing addresses as in the latter (plus the former requires
the class to define operator== as well, no?).

Yes, the former requires an accessible operator==.

Wondering if that added effort is ever justified.

Depends on a wonderous amount of factors:
(1) How the class is implemented
(2) How expensive it is to copy it
(3) How expensive it is to compare it for equality
(4) How often an object is compared to itself

If an object of the class should NEVER be assigned to itself, I would
suggest an assert:

#include <cassert>

MyClass &MyClass::opera tor=(MyClass const &rhs)
{
assert(this != &rhs);

/* Now perform assignment */

return *this;
}

--

Frederick Gotham
Sep 20 '06 #4
S S

Frederick Gotham wrote:
Chris posted:
Is there ever a reason to declare this as

if(*this == rhs)


That is not a declaration -- choose your words carefully.

as opposed to what I normally see

if(this == &rhs)


The latter compares the ADDRESSES of two objects, while the former compares
the two objects themselves.

Seems like the former version is going to be more expensive rather than
simply comparing addresses as in the latter (plus the former requires
the class to define operator== as well, no?).


Yes, the former requires an accessible operator==.

Wondering if that added effort is ever justified.


Depends on a wonderous amount of factors:
(1) How the class is implemented
(2) How expensive it is to copy it
(3) How expensive it is to compare it for equality
(4) How often an object is compared to itself

If an object of the class should NEVER be assigned to itself, I would
suggest an assert:

#include <cassert>

MyClass &MyClass::opera tor=(MyClass const &rhs)
{
assert(this != &rhs);

/* Now perform assignment */

return *this;
}
I think assert should not be good solution as we may not want to assert
just in case someone did it by mistake.

Here we can use shared pointers

class foo {
private:
std::tr1::share d_ptr<type_clas spt;
};

foo& foo::operator=( const foo& rhs)
{
pt.reset(new type_class(*rhs .pt)); //reset deletes the first and points
to 2nd,
//if new throws exception reset will not implement and original will
not be deleted.
return *this;
}

OR the other way

foo& foo::operator=( const foo& rhs)
{
type_class *pBefore = pt;
pt = new type_class(rhs. pt);
delete pt;
return *this;
}

These approaches are better as they are taking care of self assignment
saftey as well as exception saftey.

-SS
--

Frederick Gotham
Sep 20 '06 #5

S S wrote:
I think assert should not be good solution as we may not want to assert
just in case someone did it by mistake.
Well, an assert should definately not be used here but not for that
reason. Self assignment is rather common for objects when a program
gets remotely interesting. Simply not doing the assignment or devising
a way that it will just not hurt anything are the correct options.

Now, your reasoning isn't right because an assert is placed in code for
exactly that reason...in case someone accidentally violates a
pre-condition. They are there for the developer and go away in release
mode.

What you don't want is an assert that is the sole way of avoiding a
situation unless such a situation cannot be resolved, as is not the
case here. So the assert would be ok if you wanted to impose such a
restriction but the normal checks should still apply in release mode
because this could happen under conditions that where not tested and
then the program would do stupid things...and the situation is very
resolvable, you just don't do the copy.

Sep 20 '06 #6
S S posted:
I think assert should not be good solution as we may not want to assert
just in case someone did it by mistake.

An assert is the testing of a condition at runtime. If the condition is
true, nothing happens. If the condition is false:

(1) The program is terminated.
(2) The programmer is informed as to where they made their coding
error.

So you see, "assert" is used to catch programming errors quickly and to cut
down time on debugging.

Here we can use shared pointers

Overkill in my opinion.
Noah Roberts posted:
Well, an assert should definately not be used here but not for that
reason. Self assignment is rather common for objects when a program
gets remotely interesting. Simply not doing the assignment or devising
a way that it will just not hurt anything are the correct options.
If the inventor of the class deems that an object of the class should never
be assigned to itself, then an "assert" is quite appropriate. The situation
is quite akin to the following:

/* Function: CountOcc

This function counts the amount of occurrences
of a specific element in an array.

NB: (1) Neither argument may be a null pointer.
(2) The second pointer must be greater than the first.
*/

template<class T>
unsigned CountOcc(T const *pstart,T const*const pend,T const &elem)
{
assert(pstart); assert(pend); assert(pend pstart);

/* Rest of Code */
}

These asserts are very good practise in my opinion. The help the developer
without sacrificing speed of execution.

--

Frederick Gotham
Sep 20 '06 #7

Frederick Gotham wrote:
Noah Roberts posted:
Well, an assert should definately not be used here but not for that
reason. Self assignment is rather common for objects when a program
gets remotely interesting. Simply not doing the assignment or devising
a way that it will just not hurt anything are the correct options.

If the inventor of the class deems that an object of the class should never
be assigned to itself, then an "assert" is quite appropriate.
If such an inventor did indeed deem that such a pre-condition be the
case. However, that is an inappropriate precondition to enforce and
renders the class hardly usable. When designing the assignment
operator one should always be aware of, and account for (not disallow),
self-assignment. You should also try to at least provide the strong
guarantee. Both of these can often be killed with one stone simply by
accepting the parameter by value instead of by reference.

The situation
is quite akin to the following:

/* Function: CountOcc

This function counts the amount of occurrences
of a specific element in an array.

NB: (1) Neither argument may be a null pointer.
(2) The second pointer must be greater than the first.
*/

template<class T>
unsigned CountOcc(T const *pstart,T const*const pend,T const &elem)
{
assert(pstart); assert(pend); assert(pend pstart);

/* Rest of Code */
}

These asserts are very good practise in my opinion.
The first two probably, and notice how this differs a great deal from
the self assignment problem. Namely that at least the first two
pre-conditions are totally unresolvable; there is no correct answer if
those preconditions are not met whereas the answer to self assignment
is the object itself. The last isn't even valid in that the result of
the count of any specific element in an empty array should be 0, not a
blown assert...it also guarantees nothing about the validity of that
relationship between the two addresses.

Also interesting to note is that your sticking to C constructs has
resulted in a function that is not as generic as it could be. The use
of the iterator concept instead of pointers would result in a more
useful function (it could work with any container) and remove the
necissity, and in fact the possibility, of those asserts.

The fact that asserting that a ptr != 0 in many cases is rather useless
also in that the assert can pass without a valid pointer and a 0
pointer is the easiest invalid pointer to debug. Placing the assert to
advertize the precondition is enough for it to be there though.

Sep 20 '06 #8

Chris wrote:
Is there ever a reason to declare this as

if(*this == rhs)

as opposed to what I normally see

if(this == &rhs)

?

Seems like the former version is going to be more expensive rather than
simply comparing addresses as in the latter (plus the former requires
the class to define operator== as well, no?). Wondering if that added
effort is ever justified.
Why are you testing for self-assignment at all? What does the rest of
your assignment operator look like? Can you implement your operator= as
"create a temporary and swap" as in http://www.gotw.ca/gotw/059.htm.

Gavin Deane

Sep 20 '06 #9
Noah Roberts posted:
If such an inventor did indeed deem that such a pre-condition be the
case. However, that is an inappropriate precondition to enforce and
renders the class hardly usable.

I would say that that depends entirely on the kind of class we're
dealing with. Let's say we have a card game, and that we have a class
called "Hand". Let's say that we code the game in such a way that a hand
should never be compared to itself -- in fact, let's say that it would be
quite perverse if it were. In such circumstances, the "assert" solves two
problems:

(1) It informs the programmer of their coding error in Debug Mode.
(2) It doesn't burdeon the valid code in Release Mode with a decrease
in speed of execution.

When designing the assignment operator one should always be aware of,
and account for (not disallow), self-assignment.

I believe that rule is too rigid. I don't keep many rules in mind when
programming, I like to be fluidic and open to all possibilities -- it
results in more creative code (which tends to run faster too).

You should also try to at least provide the strong guarantee. Both of
these can often be killed with one stone simply by accepting the
parameter by value instead of by reference.

If speed of execution and memory consumption are no object, then yes.
<snip code>
>These asserts are very good practise in my opinion.

The first two probably, and notice how this differs a great deal from
the self assignment problem.

I believe they are very similar: They deal with something that the 3rd
party has outlawed. In the previous example, the 3rd party outlawed self-
assignment. In _this_ example, the 3rd party outlaws the passing of invalid
pointers.

Namely that at least the first two pre-conditions are totally
unresolvable; there is no correct answer if those preconditions are not
met whereas the answer to self assignment is the object itself.

Yes, but speed of execution suffers if self-assignment should trully be a
no-no. If it's extremely bizarre that an object of a certain type be
compared to itself, then we can just outlaw the practise by using an
"assert". If however it's not too weird that an object of a certain type be
compared to itself, then just go with:

if(this==&rhs)r eturn*this;

The last isn't even valid in that the result of the count of any
specific element in an empty array should be 0, not a blown assert...

This depends on whether the 3rd party considers an empty array to be an
array.

it also guarantees nothing about the validity of that relationship
between the two addresses.

Acknowledged, however it does guarantee that "pend" is ahead of "pstart"
(assuming of course that their comparisson doesn't invoke UB ; ) ).

Also interesting to note is that your sticking to C constructs has
resulted in a function that is not as generic as it could be. The use
of the iterator concept instead of pointers would result in a more
useful function (it could work with any container) and remove the
necissity, and in fact the possibility, of those asserts.

I have yet to read up on iterators; can you suggest a good book? I tried
TC++PL but didn't like the way it approached the Standard Library.

The fact that asserting that a ptr != 0 in many cases is rather useless
also in that the assert can pass without a valid pointer and a 0
pointer is the easiest invalid pointer to debug. Placing the assert to
advertize the precondition is enough for it to be there though.

Sorry I don't quite understand what you're saying in that last sentence.

--

Frederick Gotham
Sep 20 '06 #10

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

Similar topics

1
1211
by: Fredrik Bertilsson | last post by:
I am trying to overload the "and" operatior, but my __and__ method is never called. The code look like this: class Filter: column = "" operator = "" value = "" def __init__(self, col, op, val): self.column = col
45
2765
by: Jordan Rastrick | last post by:
Can anybody please give me a decent justification for this: class A(object): def __init__(self, a): self.a = a def __eq__(self, other): return self.a == other.a s = A(3)
1
1057
by: Gerardo Herzig | last post by:
Hi all. Ill try to explain mi situation: Lets say i have an DB object, who implements the querys to the database trough a method called DBObject.doQuery. On the other hand, i have 50 sql functions stored in the database. So i can call DBObject.doQuery('select * from my_sql_function()')...Ok, what do i want to achieve, is some mecanism to be able to call DBObject.my_sql_function(), but without actually having to declare the method...
0
1762
by: Pedro | last post by:
Hello pythonians! ;-D , I have a little problem when I expose (assisted by boost.python) classes with virtual functions, specially with operator(). In the C++ code below I test two different implementations of a member function of A that takes as an argument the abstract class Base (see Option 1 / Option 2): - Both compile without problems - Only the second works in python (see python program below).
9
2195
by: Emanuele Aina | last post by:
I have some code which does a lot of "in" on lists containing objects with no __eq__ defined. It all goes fast until I add the __lt__() method: then I have a slowdown comparable to the one I get using the overridden __eq__, while the __lt__ method is never called. Someone can explain me why?
4
1706
by: thorley | last post by:
I'm working with the following code. I included some tests to make it easy to see--if you run the code--what troubles I'm having. Can some one *please* splain me why str(obj) works but not print obj, and why obj.__int__() works, but not int(obj). I just don't get it. :( BTW: The reason I'm going to all this mess is that I need a Byte object that can * print like a byte e.g. \x00 * adds like a string (concatinates)
17
1465
by: Alexander Eisenhuth | last post by:
Hello, is there a assignement operator, that i can overwrite? class MyInt: def __init__(self, val): assert(isinstance(val, int)) self._val = val a = MyInt(10)
5
2451
by: raan | last post by:
What I am trying to achieve here is depicted in the small program below. // Wrapit.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <map> #include <list>
3
4248
by: Martin T. | last post by:
Hello. I tried to overload the operator<< for implicit printing of wchar_t string on a char stream. Normally using it on a ostream will succeed as std::operator<<<std::char_traits<char> will be called. However, I am using the boost::format library that internally makes use of a string stream to store the formatted string. There:
0
141
by: Gabriel Genellina | last post by:
En Thu, 25 Sep 2008 17:04:59 -0300, Arash Arfaee <erexsha@gmail.com> escribió: Because you return a plain integer from __xor__, so the _3ph "magic" is lost. Try something like this: def xor3(v1, v2): # this should implement the actual logic if v1==2 or v2==2: return 2
0
8197
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8640
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
7114
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6093
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5548
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4058
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2573
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1757
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
1438
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.