Assignment operator

Discussion in 'C++' started by Alan Ning, Nov 17, 2006.

  1. Alan Ning

    Alan Ning Guest

    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
    Alan Ning, Nov 17, 2006
    #1
    1. Advertising

  2. Alan Ning

    ondra.holub Guest

    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);
    }
    ondra.holub, Nov 17, 2006
    #2
    1. Advertising

  3. 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).

    --

    Frederick Gotham
    Frederick Gotham, Nov 17, 2006
    #3
  4. Frederick Gotham wrote:
    > [..]
    > 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 17, 2006
    #4
  5. Alan Ning

    Alan Ning Guest

    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 Bazarov wrote:
    > Frederick Gotham wrote:
    > > [..]
    > > 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
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
    Alan Ning, Nov 17, 2006
    #5
  6. Alan Ning

    Alan Ning Guest

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

    .... Alan
    Alan Ning wrote:
    > 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 Bazarov wrote:
    > > Frederick Gotham wrote:
    > > > [..]
    > > > 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
    > > --
    > > Please remove capital 'A's when replying by e-mail
    > > I do not respond to top-posted replies, please don't ask
    Alan Ning, Nov 17, 2006
    #6
  7. Alan Ning

    Rolf Magnus Guest

    Alan Ning wrote:

    > 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.

    > 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;
    > }
    Rolf Magnus, Nov 17, 2006
    #7
  8. Alan Ning

    ondra.holub Guest

    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.
    ondra.holub, Nov 17, 2006
    #8
  9. 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...

    --

    Frederick Gotham
    Frederick Gotham, Nov 17, 2006
    #9
  10. Alan Ning

    Mark P Guest

    Frederick Gotham wrote:
    > 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...
    >


    They associate right to left, of course.
    Mark P, Nov 17, 2006
    #10
  11. 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?

    --

    Frederick Gotham
    Frederick Gotham, Nov 17, 2006
    #11
  12. Alan Ning

    Squeamizh Guest

    Frederick Gotham wrote:
    > 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."
    Squeamizh, Nov 17, 2006
    #12
  13. Squeamizh:

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

    >
    > 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.

    --

    Frederick Gotham
    Frederick Gotham, Nov 17, 2006
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Wolfgang Groiss
    Replies:
    0
    Views:
    384
    Wolfgang Groiss
    Nov 19, 2003
  2. nagy
    Replies:
    36
    Views:
    962
    Terry Reedy
    Jul 20, 2006
  3. G Patel

    comma operator and assignment operator

    G Patel, Feb 7, 2005, in forum: C Programming
    Replies:
    4
    Views:
    472
    Barry Schwarz
    Feb 8, 2005
  4. Chris
    Replies:
    34
    Views:
    1,463
  5. Hicham Mouline
    Replies:
    2
    Views:
    675
    Juha Nieminen
    Sep 1, 2009
Loading...

Share This Page