Operator Overloading ( = ) - c++

I'm just a beginner in the C++ language and I have some questions on this piece of code. I am trying to overload some operators.
string& operator = (char R) { string T = R ; *this = T; return *this; }
First Question: Why I need to overload the equal operator while the constructor can do the job?
Second Question: (Not Related) What does (char R) means?

First Question: Why I need to overload the equal operator while the constructor can do the job?
The constructor is designed to "construct" an object ... while there is something called a copy-constructor, it is not designed to actually copy an already existing object into another already existing object of the same (or convertable) type ... that is the job of the operator=. Also you are not "overloading" the operator= method, but rather creating a user-defined version of the method to be used instead of the default compiler-created method for the object type which would simply brute-force copy the bits of the memory footprint of one object into another ... if your object is managing it's own pointers, etc., such a brute-force copy can be a very bad thing as pointer ownership becomes ambiguous, etc.

(char R) is the right-side argument of the operator (here =)
You want to do that so you can set a value after initialization
//constructor
Foo a('f')
//copy constructor
Foo b = Foo('p');
// operator=
b = 'g';

(char R) is the argument to the operator just like you have an argument to a normal function.

Operator overloading in C++ . One of best version here.
http://msumca2012.blogspot.in/2013/03/oop-41-operator-overloading-in-c.html

Related

How does C++ know which function to call to compute a given expression?

Typically, a standard function is called by
functionName(list of arguments).
Another standard way to call a function of an object is
object.functionName(list of arguments).
Both methods are clear and easy to understand since the function signatures are called in the exact order.
However, when it comes to the below:
A unary operator overloading: classA::operator-(), for example, doesn't take any argument. So when we write object2 = -object1,assuming object2 and object1 are both instances of classA, how does C++ know that it has to call classA::operator-() since we didn't write object2 = object1.operator-()?
A global function that defines the + operation between 2 objects for example Complex operator+(int number, const Complex& c). So when we write answer = 10 + aComplexNumber, how does C++ know which function to call since we didn't write operator+(10, aComplexNumber)?
A classA::operator[] operator overloading: so when we call object[argument]. How does C++ know which function to call since we didn't write object.operator[](argument)?
Edit: thank you all for the suggestions. I have edited my question to make it clearer.
This all depends on the operator.
Class::operator- () only operates on one item, so therefore, it does not need an argument since it can just be a member overloaded operator. (i.e. this will be operated on). This unary operator's return type should be the same as the object:
Class obj1;
obj1 = -obj1; //Calls the unary operator- and then the operator=
Now, let's suppose you want to implement the operator again but have it do operations on 2 Objects. That's where we add two different arguments and make it a non-member overloaded operator. For example: operator-(const Class & lhs, const Class & rhs), this will also most likely return an Class and will be called when you create two Class and subtract one from the other:
Class obj1;
Class obj2;
Class obj3 = obj1 - obj2; //Calls the non-member operator then operator=
Some overloaded operators must be member overloaded operators, such as the assignment operator= (const Object & rhs) and by default, the left-hand-side is this since you are assigning this Object to the rhs.
So again, it depends on the operator. You'll have to be more specific if you want more details on a specific operator.

Why *this=door is correct?

Door::Door(const Door& door)
{
*this = door;
}
I am very confused with this copy constructor. For me, it does not make sense to use *this=door, but rather
Door::Door(const Door& door)
{
this->color = door.color;
this->destination = door.destination;
}
Can you explain why *this=door is correct?
EDIT
As it is suggested, I need to overload = for the class. So I got something like
const Porte& operator =(const Porte& source)
{
this->color = door.color;
this->destination = door.destination;
}
So I am right to use *this=door now. Why isn't it rather this=door instead?
It invokes Door::operator=(Door const &other).
If that operator is explicitly implemented, it does whatever the implementation says it does. If it's implicitly generated, it simply copies the values of all members.
this is a prvalue pointer. Pointers do not have members and correspondingly you cannot apply the member access operator on a pointer.
this.color = door.color;
this.destination = door.destination;
To access the pointed object through a pointer, you must indirect through the pointer using an indirection operator. In the first program, the unary * is used which is the indirection operator.
There is also a member access indirection operator -> which is a shorthand for indirecting through a pointer and accessing member of the pointed object. As such, you could write:
this->color = door.color;
this->destination = door.destination;
The first example instead uses the assignment operator to do the same thing.
Neither of these is something that I would recommend. Best way to implement a copy constructor is in order of preference. If the first one is not applicable, then use the next and so on:
If you don't need to, don't declare copy constructor at all and use the implicitly generated one.
Define the constructor as explicitly defaulted (or deleted).
Initialise the members and leave the constructor body empty.
why it is not this=door instead?
Because it is not supposed to assign the pointer. It is supposed to assign the pointed object. As I explained above, you must indirect through the pointer (using indirection operator) in order to access the pointed object.
Besides, this is an rvalue, so it cannot be assigned.

Calling constructor within overloaded assignment operator?

Basically, is it acceptable programming practice/style to call a constructor of a class within its overloaded assignment operator? If not, why not?
EXAMPLE:
so I have a class which has 3 data members, a dynamic int array called "value" which holds digits of a large number, an int length which indicates the number of digits in the number, & an int maxLength which indicates the max length of the number (size of the dynamic array)
here's my constructor with param int:
bigInt::bigInt(const int &rhs){
//turn num_ into a string 'num'
stringstream ss;
ss << num_;
string num = ss.str();
length = strlen(num.c_str());
maxLength = (length - (length%16)) + 16;
value = new int[maxLength];
for(int i=1; i<=length; i++){
value[i-1] = num.at(length-i) - '0';
}
}
and here's my overloaded assignment operator in which the righthand side is a regular int
this method calls the constructor:
bigInt bigInt::operator=(const int &rhs){
*this = bigInt(rhs);
return *this;
}
EDIT: I guess I should have worded it differently. I didn't mean COPY constructor, but rather a regular constructor with non-class-instance parameter, and an overloaded assignment operator in which the rhs isn't the same type as the lys
There's nothing wrong with calling the copy constructor in the
implementation of an assignment operator (unless the copy
constructor itself is implemented in terms of assignment, of
course). In fact, it's a common idiom: make a local copy, then
swap the data with the current instance. (This, of course,
supposes that you have a specialized swap. Just calling
std::swap on the object itself in an assignment operator is
not a good idea. Creating a new instance, and then swapping
the individual components of the object often is. Or creating
a custom swap function which swaps the components, and calling
it.)
This is not an unreasonable way to implement your assignment operator, since it allows you to utilize existing code, and provides the strong guarantee as long as your copy assignment operator does.
Two points of note however: First, make sure that your copy constructor, copy assignment operator, and destructor are all implemented properly or you'll start having memory management problems. Second, the C++ language ALREADY provides a class with elements, a length, and a max length: It's called std::vector and if you change your code to use it, you don't need to write the copy constructor, copy assignment operator, and destructor at all, as they'll just behave properly!
Also, your assignment operator should return by reference (or if you really don't want chaining, void). Returning by value will someday cause a bug when a chained assignment doesn't work as expected.
The opposite is better. It's perfectly fine.
However, don't forget that in the copy contructor you MUST redo what you do in the constructor; i.e., initialize any variables you have in your class, which is not necessary to be done in the overloaded assignment operator function.

Best way to overload the C++ assignment operator

I have a class A which dynamically allocates memory for an integer(pointed by a class memeber say _pPtrMem) in its constructor and deallocates the same in destructor. To avoid Shallow copy, I have overloaded assignment operator and copy constructor. The widely used way in which assignment operator is overloaded is as following:
A& operator = (const A & iToAssign)
{
if (this == & iToAssign) // Check for self assignment
return *this;
int * pTemp = new int(*(iToAssign._pPtrMem)); // Allocate new memory with same value
if (pTemp)
{
delete _pPtrMem; // Delete the old memory
_pPtrMem = pTemp; // Assign the newly allocated memory
}
return *this; // Return the reference to object for chaining(a = b = c)
}
Another way for implementing the same could be
A& operator = (const A & iToAssign)
{
*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
return *this;
}
Since the second version is comparatively much simpler and faster(no deallocation, allocation of memory) why is it not used widely? Any problems that I am not able to make out?
Also we return an object of the same type from the assignment operator for chaining(a = b = c)... so instead of returning *this is it fine to return the iToAssign object as both objects are supposedly now equal?
Usually, the best way to implement a copy assignment operator is to provide a swap() function for your class (or use the standard one if it does what you want) and then implement the copy assignment operator via the copy constructor:
A& A::operator= (A iToAssign) // note pass by value here - will invoke copy constructor
{
iToAssign.swap(*this);
return *this;
}
// void swap(A& other) throws() // C++03
void A::swap(A& other) noexcept
{
std::swap(_pPtrMem, other._pPtrMem);
}
This makes sure that your copy assignment operator and copy constructor never diverge (that is, it cannot happen that you change one and forget to change the other).
No, there is no problem with your implementation. But having one integer dynamic allocated is at least very special.
This implementation is not widely used, because no one allocates a single integer on the free store. You usually use dynamic allocated memory for arrays with a variable length unknown at compile time. And in this case it's most of the time a good idea to just use std::vector.
No it's not fine, to return an different object. Identity is not the same as equality:
T a, b, d;
T& c = a = b;
c = d; // should change a, not b
Would you expect that the third line changes b?
Or a event better Example:
T a;
T& b = a = T();
This would result in a dangling reference, referencing an temporary and destructed object.
The first version is used in case _pPtrMem is a pointer to some basic type for instance a dynamically allocated array. In case the pointer is pointing to a single object with correctly implemented assignment operator the second version will do just as good. But in that case I don't think you will need to use a pointer at all.
In the second case, if _pPtrMem was initially unassigned, the line
*_pPtrMem= *(iToAssign._pPtrMem); // Just copy the values
is causing an assignment to an invalid memory location (possibly a segmentation fault). This can only work if _pPtrMem has been allocated memory prior to this call.
In this case, the second implementation is by far the better.
But the usual reason for using dynamic in an object is because
the size may vary. (Another reason is because you want the
reference semantics of shallow copy.) In such cases, the
simplest solution is to use your first assignment (without the
test for self-assignment). Depending on the object, one might
consider reusing the memory already present if the new value
will fit; it adds to the complexity somewhat (since you have to
test whether it will fit, and still do the
allocation/copy/delete if it doesn't), but it can improve
performance in certain cases.

assignment operator return a reference to *this in C++

I read about this from "Effective c++" ,this is Col.10.
It say it's a good way to have assignment operators return a reference to *this.
I wrote a code snippet to test this idea. I overridden the assignment operator here.And tested it. Everything is fine.
But when I remove that operator overriding, everything is the same. That means, the chaining assignment still works well. So, what am I missing? Why is that? Need some explanation from you guys, THank you.
#include <iostream>
using namespace std;
class Widget{
public:
Widget& operator=(int rhs)
{
return *this;
}
int value;
};
int main()
{
Widget mywidget;
mywidget.value = 1;
Widget mywidget2;
mywidget2.value = 2;
Widget mywidget3 ;
mywidget3.value = 3;
mywidget = mywidget2 = mywidget3;
cout << mywidget.value<<endl;
cout << mywidget2.value<<endl;
cout << mywidget3.value<<endl;
}
If you remove completely the operator= method, a default operator= will be created by the compiler, which implements shallow copy1 and returns a reference to *this.
Incidentally, when you write
mywidget = mywidget2 = mywidget3;
you're actually calling this default operator=, since your overloaded operator is designed to work with ints on the right side.
The chained assignment will stop working, instead, if you return, for example, a value, a const reference (=>you'll get compilation errors) or a reference to something different from *this (counterintuitive stuff will start to happen).
Partially related: the copy and swap idiom, i.e. the perfect way to write an assignment operator. Strongly advised read if you need to write an operator=
The default operator= will perform as if there were an assignment between each member of the left hand operand and each member of the right hand one. This means that for primitive types it will be a "brutal" bitwise copy, which in 90% of cases isn't ok for pointers to owned resources.
The question touches two different concepts, whether you should define operator= and whether in doing so you should return a reference to the object.
You should consider the rule of the three: if you define one of copy constructor, assignment operator or destructor you should define the three of them. The rationale around that rule is that if you need to provide a destructor it means that you are managing a resource, and in doing so, chances are that the default copy constructor and assignment operator won't cut it. As an example, if you hold memory through a raw pointer, then you need to release the memory in the destructor. If you don't provide the copy constructor and assignment operator, then the pointer will be copied and two different objects will try to release the memory held by the pointer.
While a pointer is the most common example, this applies to any resource. The exception is classes where you disable copy construction and assignment --but then again you are somehow defining them to be disabled.
On the second part of the question, or whether you should return a reference to the object, you should. The reason, as with all other operator overloads is that it is usually a good advice to mimic what the existing operators for basic types do. This is sometimes given by a quote: when overloading operators, do as ints do.
Widget& operator=(int rhs)
This allows you to assign an int to a Widget - e.g. mywidget = 3;
Make a Widget& operator=(Widget const & rhs) - it'll be called for your mywidget = mywidget2 = mywidget3; line.
You do not need an operator=(Widget const & rhs) though - the default should do fine.
Also, it may be a good idea to add e.g. cout << "operator=(int rhs)\n"; to your custom operator - then you'd see that it didn't get called at all in your code.