This question already has answers here:
Difference between returning reference vs returning value C++
(3 answers)
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 8 years ago.
MyClass& operator=(const MyClass& other)
{
//Implement
return *this;
}
MyClass operator=(const MyClass& other)
{
//Implement
return *this;
}
void operator=(const MyClass& other)
{
//Implement
}
When I test these methods, the result is the same. In almost book I see that the first method(MyClass&) is used more than the second method. what's different between them? Which method is really right and fast? One method return address and the second return value.
When I test these methods, the result is the same.
it depends on how you test your class, ie.:
void foo (MyClass& a);
MyClass a1;
MyClass a2;
foo(a1 = a2);
in case of second operator implementation (returning MyClass), above code (inside foo) will not modify a1 instance, but a temporary value.
In almost book I see that the first method(MyClass&) is used more than
the second method.
and thats correct, its more correct to return reference to *this in assignment operator
what's different between them? Which method is really right and fast?
first version is faster and correct because it does not do any copy of your object, also its more proper because thats how primitive types behave, ie:
int n = 0;
int k = 10;
(n = k) = 1;
std::cout << n;
here on output you will get 1, because (n = k) returns reference to n.
Related
This question already has answers here:
Return type of assignment operator
(1 answer)
Why must the copy assignment operator return a reference/const reference?
(8 answers)
Closed 5 years ago.
Let's say there is this code:
struct Tester
{
int value = 0;
void operator=(const Tester& original)
{
value = original.value;
}
};
Purpose of overriding operator= is to use it like normal assignment operator. This function would definitely take parameter's "value" and put it to host object's "value".
However, other programmers suggest to use:
Tester& operator=(const Tester& original)
{
value = original.value;
return *this;//edited
}
with return type of Tester as reference. The first function would do exactly the same. Why and how would that be useful?
The first function would do exactly the same
Not quite. The second version you posted omits a return statement. So it has undefined behavior. But once it's fixed:
Tester& operator=(const Tester& original)
{
value = original.value;
return *this;
}
It can be used to chain assignments:
a = b = c;
Something your void version cannot be used for.
This question already has answers here:
Why should the assignment operator return a reference to the object?
(4 answers)
Closed 8 years ago.
I have written a class in C++ and have defined assignment operator function:
cplusplus.com recommends following syntax.
check operator= (const check& obj){*cstr = *(obj.cstr); return *this;}
One another syntax is:
void operator= (const check& obj){*cstr = *(obj.cstr);} # Not returning *this
Would you recommend using first method or the second?
Following is my class:
class check {
private:
string * cstr;
public:
int a;
check (string str) { cstr = new string(str);}
check (const check& obj) {cstr = obj.cstr;}
~check() {cout<<"DES"<<endl; delete cstr; }
check operator= (const check& obj){*cstr = *(obj.cstr); return *this;}
void display () { cout<<*cstr<<endl;}
};
int main () {
check da {"one"};
check pa {"two"};
pa = da;
have (pa);
return 0;
}
The usual way of writing the assignment operator is actually
check &operator= (const check& obj){*cstr = *(obj.cstr); return *this;}
i.e., returning a reference to itself. This matches the semantics of assignment for built-in types. Returning check by value may incur an unnecessary copy if the return value is not used. Returning void means you can't write check1 = check2 = check3;.
By the way, check (const check& obj) {cstr = obj.cstr;} is probably wrong. You'd want your copy constructor to make a deep copy and not just copy a pointer. Moreover, I see no reason you need to use a pointer as a class member. If you just store a plain std::string, you can simply use the compiler-generated copy constructor and copy assignment operators.
I am a beginner in C++, and this must be a really basic question. I understand & stands for referencing operation. For example, a = &b assigns the address of b to a. However, what does & in a declaration such as the following mean?
className& operator=(const className&);
Do the following make sense and what is the difference between the last line and the following?
className* operator=(const className*);
From the answers below, it seems --- as I understand it --- that the following is valid too. Is it? If it is, how is it different from the version with "&"?
className operator=(const className);
After reading the following answers and some more outside, I realized part of my original confusion stems from mixing up reference as in general computer science and reference type as in C++. Thank you all who answered my question. All the answers clarify my understanding to different degrees, even though I can only pick one as the accepted answer.
The token & has three distinct meanings in C++, two of which are inherited from C, and one of which is not.
It's the bitwise AND operator (unless overloaded).
It's the address operator, which acts on an lvalue to yield a pointer to it. (Unless overloaded.) This is what is happening in a = &b.
It denotes a reference type. const className& as a parameter is a const reference to an object of type className, so when the function is called, the argument will be passed by reference, but it won't be allowed to be modified by the function. The function you gave also returns a reference.
Assignment Operator
Understanding is best gained by example:
class A {
int x;
public:
A(int value) : x(value) {}
A& operator=(const A& from) { // Edit: added missing '=' in 'operator='
x = from.x;
return *this;
}
};
A m1(7);
A m2(9);
m2 = m1; /// <--- calls the function above, replaces m2.x with 7
Here, we defined the assignment operator. This special method is designed to provide assignment capability to objects.
The reason that it returns a reference to *this is so you can chain assignments without excessive memory copies:
A m3(11);
m3 = m1 = m2; /// <--- now, m3.x and m1.x both set to m2.x
Expanded as follows:
m3 = ( something )
where
(something) is a reference to the object m1
by result of call to m1.operator=(m2) method
such that
the returned reference is then passed into m3.operator(...)
Chaining lets you do this:
(m1=m2).function(); // calls m1.function after calling assignment operator
Libraries such as boost leverage this pattern (for a different type of chaining example, see the program options library in boost) and it can be useful when developing a domain specific 'language'.
If instead full objects were returned from operator=, the chained assignment would at a minimum involve multiple extra copies of the objects, wasting CPU cycles and memory. In many cases things would not work properly because of the copy.
Essentially, using a reference avoids a copy.
Note
In reality, (simplified explanation) a reference is just a fancy syntax for a C pointer.
In the common case, you can then write code with A.x instead of A->x.
Caution
Returning a pure reference from a method is often dangerous; newcomers can be tempted to return a reference to an object constructed locally inside the method on the stack, which depending on the object can lead to obscure bugs.
Your pointer example
It depends on what you return from the body of the method, but regardless, the following would instead return a pointer to some instance of className:
className* operator=(const className*);
This will compile and it even seems to work (if you return this from the method), but this does violate the Rule of Least Surprise, as it is likely anyone else attempting to use your code would not expect the assignment operator to return a pointer.
If you think about base types:
int x=1; int y=2; int z; z=y=x;
will never ever do anything other than return integers - so having operator= return the assigned to object is consistent)
It also doesn't let you do this:
(m1 = m2).something
It also allows you to pass NULL which is something assignment operators don't typically want to care about.
Instead of writing
blah& operator(const blah& x) { a = x.a ; return *this; }
You would need to write:
blah* operator(const blah* x) {
if (x) { a = x->a ; return this; }
else { /*handle null pointer*/
}
It means the function takes a reference to a const className and returns a reference to a className
Say you have a class like below:
class className
{
public:
className& operator=(const className& rhs)
{
this->a_ = rhs.a_;
this->b_ = rhs.b_;
return *this;
}
private:
std::string a_;
std::string b_;
};
You can use the assignment operator of the class as below:
className a;
className b;
className c;
c = b = a;
The above line is executed as:
c.operator=(b.operator=(a));
Now take another class that has the operator= defined using the second form:
class className2
{
public:
className2* operator=(const className2* rhs)
{
this->a_ = rhs->a_;
this->b_ = rhs->b_;
return this;
}
private:
std::string a_;
std::string b_;
};
You can use the assignment operator of the class as below:
className2 obj1;
className2 obj2;
className2 obj3;
obj2 = &obj1;
obj3 = &obj2;
The above lines are executed as:
obj2.operator=(&obj1);
obj3.operator=(&obj2);
However, such coding is not intuitive. You don't assign a pointer to an object. It is more intuitive to say:
className obj1;
className* objPtr = NULL;
objPtr = &obj1;
a = &b
Here, & gives address of b.
className& operator=(const className&);
Here, operator = will take const reference of variable of type className.
You can say in C++, & is polymorphic.
This question already has answers here:
Why must the copy assignment operator return a reference/const reference?
(8 answers)
Closed 8 years ago.
I've tried to understand what is the purpose of reference returning in this code ? Is it just because returning reference is much faster than copy or is there something else more important ??
class Container
{
public:
int Elems;
int * data;
Container(int n):Elems(n){data=new int[Elems];}
Container operator= (const Container &rhs);
};
Container & Container:: operator= (const Container & rhs)
{// I deleted the & and I can still compiled and make such things (a=b=c)
if(this!=&rhs)
{
if(data!=NULL)
{
delete [] data;
}
Elems=rhs.Elems;
data=new int[Elems];
for(int i=0;i<Elems;i++)
data[i]=rhs.data[i];
}
return *this;
}
Yes, it's to avoid unneeded copies. In the case of this particular class, though, it's needed for correctness, as there's no proper copy constructor. Default copying instances of this class will result in multiple instances sharing the same data member, and will likely result in multiple deletes.
In C++ function signatures do not depend on the return type, so the return is ignored when overloading.
Before C++11, returning a value instead of a reference would incur in copy overhead.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Operator overloading
EDIT 2
I was using insert(...) incorrectly, I didn't actually need a '=' operator. Sorry to waste peoples' time. I have voted to close.. 2 votes remain. Please vote.
EDIT
The reason I want an '=' operator is so I can use the insert(...) function on a vector of Derivation objects. At the moment my compiler says:
/usr/include/c++/4.2.1/bits/stl_algobase.h:283: error: no match for 'operator=' in '* __result = * __first'
I have created '==' and '<' operators for my own classes before but I'm struggling to create an '=' operator. My class looks like this (ignore the silly variable names):
class Derivation {
public:
string rc;
ImplementationChoice Y;
vector<Derivation> X;
vector<string> D;
vector<string> C;
vector<Player> P, O;
vector<Attack> B;
// various functions
// ...
};
and I want to know what I need to put in
// What do '=' return? An object of the class right?
Derivation& operator=(const Derivation &d) const {
// something....
}
Many thanks.
First, an assignment operator probably should not be const--
Second, assignment operators usually return a non-const reference to the object that was assigned a value (*this)
You don't need one. The compiler-generated one will do just fine.
first remove the const ...
then if you really need a copy operator, do something like that and add your own logic (so that it doesn't do just exactly what would be done with the compiler generated copy operator) :
Derivation& operator=(const Derivation& other) {
this->rc = other.rc;
this->Y = other.Y;
this->X = other.X;
this->D = other.D;
this->C = other.C;
this->P = other.P;
this->O = other.O;
this->B = other.B;
// ...
return *this;
}
This is up to you, really. What do you need the operator to do? Do you want to return a reference, or do you want a copy?
EDIT: Please note that this was rhetorical. What you use this vector for will determine if you need a reference or a copy. For example, if the object your inserting is at any point going to go out of scope before being removed from the vector, you'll want a copy. If not, and you want the original object to be effected when you change the instance in the vector, you'll want a reference. Hope that helps a bit.
The standard way to implement an assignment operator is copy-and-swap.
This has the advantages of being the most simple way to make an assignment operator that is correct in the face of exceptions and self-assignment. It also defines the assignment operation in terms of the copy-constructor, thus reducing the number of places where your code needs to be changed if you add extra members to the class.
Anyway - here is what it looks like in your case:
class Derivation {
public:
string rc;
ImplementationChoice Y;
vector<Derivation> X;
vector<string> D;
vector<string> C;
vector<Player> P, O;
vector<Attack> B;
//You need to add a swap function to your class
void swap(Derivation& o) {
rc.swap(o.rc);
Y.swap(o.Y);//Assuming ImplementationChoice has a swap function (it should!)
X.swap(o.X);
D.swap(o.D);
C.swap(o.C);
P.swap(o.P);
O.swap(o.O);
B.swap(o.B);
}
Derivation& operator=(Derivation const& o) {
Derivation copy(o);
copy.swap(*this);
return *this;
}
// various functions
// ...
};
to overload assignment operator you should do this
Derivation& operator=(const Derivation &d) {
// something....
return *this
}
This will allow you to do something like.
Deviation a, b, c;
//something
c = b = a;
Since - #jalf has not put up an answer, here it is :)
Derivation& operator=(const Derivation &d) {
// something....
return *this;
}
You need to return a reference to this instance. this is a keyword which holds a pointer to the instance on which the operator is acting.