Assignment operator

A

Alan Ning

I have a question on assignment operator.

People in my company likes to make their assignment operator const.

So we have

const A& operator=(const A& obSrc)


But everywhere online, I see

A& operator=(const A& obSrc)


What is the difference? They both seem to work just fine.

Thanks

.... Alan
 
O

ondra.holub

The only difference is that you cannot change result of assignment when
it is defined as const (that means, it may not be passed as non-const
parameter to any function). See example:

class A
{
public:
A() { }

A& operator=(const A& src) { return *this; }

void NonConstMethod() { }
};

void Fn(A& a)
{
}

class B
{
public:
B() { }

const B& operator=(const B& src) { return *this; }

void NonConstMethod() { }
};

void Fn(B& b)
{
}

int main()
{
A a1, a2;
(a2 = a1).NonConstMethod(); // It works (but who uses it this way?)
Fn(a2 = a1); // It works too and can be quite normal (but is not
necessary)

B b1, b2;
//(b2 = b1).NonConstMethod(); // It does not work
//Fn(b2 = b1); // It does not work too

b2 = b1;
b2.NonConstMethod();
Fn(b2);
}
 
F

Frederick Gotham

Alan Ning:
I have a question on assignment operator.

People in my company likes to make their assignment operator const.

So we have

const A& operator=(const A& obSrc)


But everywhere online, I see

A& operator=(const A& obSrc)


What is the difference? They both seem to work just fine.


The whole point of operator overloading is that you can get your own class
objects to behave like intrinsic types, e.g. add to them, dereference them,
array subscript them.

C++, however, gives you full control -- almost _too_ full control -- over
how you wish to implement an operator for your given class. For instance, I
can make the multiplication operator perform a division instead of a
multiplication:

MyClass &MyClass::eek:perator*=(MyClass const &rhs)
{
some_member /= rhs.some_member;

return *this;
}

This is perfect OK... but is it good? Of course, you'd have no know the
requirements of the project and so forth to give a definitive answer, but
the general answer is: No, this is not good, it's operator abuse.

Let's look at the assignment operator. With normal types, you can do the
following:

int a,b,c,d,e,f,g=5;

a=b=c=d=e=f=g;

If you try this with your sample code which returns a "MyClass const&"
rather than a "MyClass&", then you'll get a compile error.

In my own opinion, the general view of this should be that it's operator
abuse -- i.e. it's not natural to not be able to perform multiple
assignments in the one statement.

Of course, there are umpteen bad programming styles out there which seem to
flourish, so if you like the bastardisation of returning a "MyClass
const&", then go for it.

My own opinion however is that it's operator abuse.

(But then again, one size doesn't fit all -- you may be writing a strange
class where you wouldn't want to allow multiple assignments, but of course,
this is the "odd-one-out" scenario).
 
V

Victor Bazarov

Frederick said:
[..]
Let's look at the assignment operator. With normal types, you can do
the following:

int a,b,c,d,e,f,g=5;

a=b=c=d=e=f=g;

If you try this with your sample code which returns a "MyClass const&"
rather than a "MyClass&", then you'll get a compile error.

REALLY? Compile this:

struct A {
const A& operator=(const A&);
};

int main() {
A a,b,c,d,e,f,g;
a=b=c=d=e=f=g;
}

and then explain.

V
 
A

Alan Ning

Interesting code, Frederick Gotham

I tried something similar, but A is a class instead of a struct.

In GNU G++, it compiled, but the program segfaulted.

So I tried to take out the const in the operator=, it segfaulted again.


Here's my code...

#include <iostream>
using namespace std;

class A
{
public:
const A & operator=(const A &robSrc) { i = robSrc.i; };
int i;
};

int main()
{
A obA;
A obCopyA;
A obCopyA2;
A obCopyA3;

obA.i = 1983;
obCopyA = obCopyA2 = obA; // crash...

cout << "obA - " << obA.i << endl;
cout << "obCopyA - " << obCopyA.i << endl;
cout << "obCopyA2 - " << obCopyA2.i << endl;

return 0;
}



.... Alan

Victor said:
Frederick said:
[..]
Let's look at the assignment operator. With normal types, you can do
the following:

int a,b,c,d,e,f,g=5;

a=b=c=d=e=f=g;

If you try this with your sample code which returns a "MyClass const&"
rather than a "MyClass&", then you'll get a compile error.

REALLY? Compile this:

struct A {
const A& operator=(const A&);
};

int main() {
A a,b,c,d,e,f,g;
a=b=c=d=e=f=g;
}

and then explain.

V
 
A

Alan Ning

NM, I forgot "return *this" in the assignment operator. I am an
idiot...

.... Alan
Alan said:
Interesting code, Frederick Gotham

I tried something similar, but A is a class instead of a struct.

In GNU G++, it compiled, but the program segfaulted.

So I tried to take out the const in the operator=, it segfaulted again.


Here's my code...

#include <iostream>
using namespace std;

class A
{
public:
const A & operator=(const A &robSrc) { i = robSrc.i; };
int i;
};

int main()
{
A obA;
A obCopyA;
A obCopyA2;
A obCopyA3;

obA.i = 1983;
obCopyA = obCopyA2 = obA; // crash...

cout << "obA - " << obA.i << endl;
cout << "obCopyA - " << obCopyA.i << endl;
cout << "obCopyA2 - " << obCopyA2.i << endl;

return 0;
}



... Alan

Victor said:
Frederick said:
[..]
Let's look at the assignment operator. With normal types, you can do
the following:

int a,b,c,d,e,f,g=5;

a=b=c=d=e=f=g;

If you try this with your sample code which returns a "MyClass const&"
rather than a "MyClass&", then you'll get a compile error.

REALLY? Compile this:

struct A {
const A& operator=(const A&);
};

int main() {
A a,b,c,d,e,f,g;
a=b=c=d=e=f=g;
}

and then explain.

V
 
R

Rolf Magnus

Alan said:
Interesting code, Frederick Gotham

I tried something similar, but A is a class instead of a struct.

Doesn't matter.
In GNU G++, it compiled, but the program segfaulted.

You should increase the warning level. Like:

g++ -ansi -pedantic -Wextra -Wall assop.cpp -o assop
assop.cpp: In member function ‘const A& A::eek:perator=(const A&)’:
assop.cpp:7: warning: no return statement in function returning non-void
assop.cpp: In function ‘int main()’:
assop.cpp:16: warning: unused variable ‘obCopyA3’
assop.cpp: In member function ‘const A& A::eek:perator=(const A&)’:
assop.cpp:7: warning: control reaches end of non-void function
So I tried to take out the const in the operator=, it segfaulted again.


Here's my code...

#include <iostream>
using namespace std;

class A
{
public:
const A & operator=(const A &robSrc) { i = robSrc.i; };

You forgot to actually return something. This is the reason for the crash.
 
O

ondra.holub

Multiple assignment works also for normally overloaded assignment
operator returning reference to constant, because it in normal case
gets as parameter (right operand) reference to constant too. Of course,
there are some exceptions, for example std::auto_ptr, which has to
change right operand during assignment, but these are rare cases.
 
F

Frederick Gotham

Victor Bazarov:
REALLY? Compile this:

struct A {
const A& operator=(const A&);
};

int main() {
A a,b,c,d,e,f,g;
a=b=c=d=e=f=g;
}

and then explain.


I'm at a loss here Victor, can you please expain this to me?

The questions that come to mind are:

(1) Why isn't there a linkage error? There's no definition of A::eek:perator=.
(2) Even if there were a definition of operator=, it would return a
"reference to const", and a non-const member function should not be allowed
to be invoked upon it.

And there I was thinking I sort of knew this stuff inside out...
 
M

Mark P

Frederick said:
Victor Bazarov:



I'm at a loss here Victor, can you please expain this to me?

The questions that come to mind are:

(1) Why isn't there a linkage error? There's no definition of A::eek:perator=.
(2) Even if there were a definition of operator=, it would return a
"reference to const", and a non-const member function should not be allowed
to be invoked upon it.

And there I was thinking I sort of knew this stuff inside out...

They associate right to left, of course.
 
F

Frederick Gotham

Mark P:
They associate right to left, of course.

a.operator=(b.operator=(c.operator=(d.operator=(e.operator=(f.operator=
(g))))));

Oh wait, I just copped it. Only the following would be illegal:

(a=b) = c;

But I still don't understand why there isn't a linkage error?
 
S

Squeamizh

Frederick said:
Oh wait, I just copped it. Only the following would be illegal:

(a=b) = c;

But I still don't understand why there isn't a linkage error?

He said "compile this."
 
F

Frederick Gotham

Squeamizh:
He said "compile this."


Okey dokey, here's what happened.

I first compiled it as a single translation unit, and there was no problem.

I then "fully" compiled it as a program consisting of a single translation
unit, and it entire thing worked. Of course, I suprised that there wasn't a
linkage error.

Anyhow, I've used a different compiler now, and thankfully, I get a linker
error.

Case closed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top