assignment operator

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • subramanian100in@yahoo.com, India

    #1

    assignment operator

    For a class Test, we write the assignment operator as

    Test & Test::operator= (const Test & rhs);

    instead of

    const Test & Test::operator= (const Test & rhs);

    that is, the return type of operator=( ) is just a reference, not a
    reference to const object.

    is it because to allow for expressions such as

    (x = y) + z;
    where x, y, z are of type Test ?

    What would happen if we allowed "const Test &" as the return type of
    Test::operator= ( ) ?

    Kindly clarify.

    Thanks
    V.Subramanian

  • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

    #2
    Re: assignment operator

    On 2007-09-23 12:28, subramanian100i n@yahoo.com, India wrote:
    For a class Test, we write the assignment operator as
    >
    Test & Test::operator= (const Test & rhs);
    >
    instead of
    >
    const Test & Test::operator= (const Test & rhs);
    >
    that is, the return type of operator=( ) is just a reference, not a
    reference to const object.
    >
    is it because to allow for expressions such as
    >
    (x = y) + z;
    where x, y, z are of type Test ?
    >
    What would happen if we allowed "const Test &" as the return type of
    Test::operator= ( ) ?
    >
    Kindly clarify.
    I would say it is because there is no reason to return a const reference
    (since the object referred to is not const) and it does allow us to do
    some things that a const reference would not. Your example above "(x =
    y) + z;", however, should work even with a const reference, the
    following would not "(x = y) += z;", but on the other hand you should
    probably write such code in the first place. Notice also that the other
    unary operators, such as +=, *=, etc., return a non-const reference.

    --
    Erik Erikström

    Comment

    • Kai-Uwe Bux

      #3
      Re: assignment operator

      subramanian100i n@yahoo.com, India wrote:
      For a class Test, we write the assignment operator as
      >
      Test & Test::operator= (const Test & rhs);
      >
      instead of
      >
      const Test & Test::operator= (const Test & rhs);
      >
      that is, the return type of operator=( ) is just a reference, not a
      reference to const object.
      >
      is it because to allow for expressions such as
      >
      (x = y) + z;
      where x, y, z are of type Test ?
      Not really. The following compiles just fine:

      class Test {
      public:

      Test const & operator= ( Test const & other ) {
      return ( *this );
      }

      Test operator+ ( Test const & rhs ) const {
      return ( *this );
      }

      };

      int main ( void ) {
      Test a;
      Test b;
      Test c;
      ( a = b ) + c;
      }

      It's more expressions like this:

      swap( a=b, c );

      Now, you would not really want that in your code anyway.
      What would happen if we allowed "const Test &" as the return type of
      Test::operator= ( ) ?
      Well, it is allowed. What happens, is that you could not call non-const
      methods on the returned reference. Since the return is usually ignored, it
      does not really matter all that much. You could even make operator= return
      void. The compiler will not care.


      Best

      Kai-Uwe Bux

      Comment

      • Michal Nazarewicz

        #4
        Re: assignment operator

        On 2007-09-23 12:28, subramanian100i n@yahoo.com, India wrote:
        >For a class Test, we write the assignment operator as
        >>
        >Test & Test::operator= (const Test & rhs);
        >>
        >instead of
        >>
        >const Test & Test::operator= (const Test & rhs);
        >>
        >that is, the return type of operator=( ) is just a reference, not a
        >reference to const object.
        >>
        >is it because to allow for expressions such as
        >>
        >(x = y) + z;
        >where x, y, z are of type Test ?
        >>
        >What would happen if we allowed "const Test &" as the return type of
        >Test::operator =( ) ?
        Erik Wikström <Erik-wikstrom@telia. comwrites:
        I would say it is because there is no reason to return a const reference
        (since the object referred to is not const) and it does allow us to do
        some things that a const reference would not. Your example above "(x =
        y) + z;", however, should work even with a const reference,
        How come? There is no "operator=(cons t Test&)const", so how could it
        work?
        the
        following would not "(x = y) += z;", but on the other hand you should
        probably write such code in the first place. Notice also that the other
        unary operators, such as +=, *=, etc., return a non-const reference.
        Those are not unary operators and they return the type you specify which
        should be const reference.

        Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
        = c" to work and thus they should not work. Operator overloading is not
        for creating new syntax.

        --
        Best regards, _ _
        .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
        ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
        ooo +--<mina86*tlen.pl >--<jid:mina86*jab ber.org>--ooO--(_)--Ooo--

        Comment

        • Kai-Uwe Bux

          #5
          Re: assignment operator

          Michal Nazarewicz wrote:
          >On 2007-09-23 12:28, subramanian100i n@yahoo.com, India wrote:
          >>For a class Test, we write the assignment operator as
          >>>
          >>Test & Test::operator= (const Test & rhs);
          >>>
          >>instead of
          >>>
          >>const Test & Test::operator= (const Test & rhs);
          >>>
          >>that is, the return type of operator=( ) is just a reference, not a
          >>reference to const object.
          >>>
          >>is it because to allow for expressions such as
          >>>
          >>(x = y) + z;
          >>where x, y, z are of type Test ?
          >>>
          >>What would happen if we allowed "const Test &" as the return type of
          >>Test::operato r=( ) ?
          >
          Erik Wikström <Erik-wikstrom@telia. comwrites:
          >I would say it is because there is no reason to return a const reference
          >(since the object referred to is not const) and it does allow us to do
          >some things that a const reference would not. Your example above "(x =
          >y) + z;", however, should work even with a const reference,
          >
          How come? There is no "operator=(cons t Test&)const", so how could it
          work?
          >
          >the
          >following would not "(x = y) += z;", but on the other hand you should
          >probably write such code in the first place. Notice also that the other
          >unary operators, such as +=, *=, etc., return a non-const reference.
          >
          Those are not unary operators and they return the type you specify which
          should be const reference.
          They are assignment operators; and for built in types, they return lvalues.

          Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
          = c" to work and thus they should not work.
          Those programmers expect wrongly. These expressions work just fine for built
          in types:

          #include <iostream>

          int main ( void ) {
          int a = 3;
          int b = 2;
          int c = 4;
          int d = 3;
          ( a += b ) = ( c = d );
          std::cout << a;
          std::cout << b;
          std::cout << c;
          std::cout << d;
          }

          Operator overloading is not for creating new syntax.
          In the above code, the syntax you abhor is neither new nor created by
          operator overloading.



          Best

          Kai-Uwe Bux

          Comment

          • Kai-Uwe Bux

            #6
            Re: assignment operator

            Kai-Uwe Bux wrote:
            Michal Nazarewicz wrote:
            >
            >>On 2007-09-23 12:28, subramanian100i n@yahoo.com, India wrote:
            >>>For a class Test, we write the assignment operator as
            >>>>
            >>>Test & Test::operator= (const Test & rhs);
            >>>>
            >>>instead of
            >>>>
            >>>const Test & Test::operator= (const Test & rhs);
            >>>>
            >>>that is, the return type of operator=( ) is just a reference, not a
            >>>reference to const object.
            >>>>
            >>>is it because to allow for expressions such as
            >>>>
            >>>(x = y) + z;
            >>>where x, y, z are of type Test ?
            >>>>
            >>>What would happen if we allowed "const Test &" as the return type of
            >>>Test::operat or=( ) ?
            >>
            >Erik Wikström <Erik-wikstrom@telia. comwrites:
            >>I would say it is because there is no reason to return a const reference
            >>(since the object referred to is not const) and it does allow us to do
            >>some things that a const reference would not. Your example above "(x =
            >>y) + z;", however, should work even with a const reference,
            >>
            >How come? There is no "operator=(cons t Test&)const", so how could it
            >work?
            >>
            >>the
            >>following would not "(x = y) += z;", but on the other hand you should
            >>probably write such code in the first place. Notice also that the other
            >>unary operators, such as +=, *=, etc., return a non-const reference.
            >>
            >Those are not unary operators and they return the type you specify which
            >should be const reference.
            >
            They are assignment operators; and for built in types, they return
            lvalues.
            >
            >
            >Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
            >= c" to work and thus they should not work.
            >
            Those programmers expect wrongly. These expressions work just fine for
            built in types:
            >
            #include <iostream>
            >
            int main ( void ) {
            int a = 3;
            int b = 2;
            int c = 4;
            int d = 3;
            ( a += b ) = ( c = d );
            std::cout << a;
            std::cout << b;
            std::cout << c;
            std::cout << d;
            }
            >
            >
            >Operator overloading is not for creating new syntax.
            >
            In the above code, the syntax you abhor is neither new nor created by
            operator overloading.
            Since the discussion was about syntax, I forgot to mention semantics:

            ( a = b ) = c

            is well-defined for user defined types since the overloaded operators are
            functions and create sequence points. For built in types, the variable a is
            modified twice between sequence points and the behavior is undefined.



            Best

            Kai-Uwe Bux

            Comment

            • =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=

              #7
              Re: assignment operator

              On 2007-09-23 13:32, Michal Nazarewicz wrote:
              >On 2007-09-23 12:28, subramanian100i n@yahoo.com, India wrote:
              >>For a class Test, we write the assignment operator as
              >>>
              >>Test & Test::operator= (const Test & rhs);
              >>>
              >>instead of
              >>>
              >>const Test & Test::operator= (const Test & rhs);
              >>>
              >>that is, the return type of operator=( ) is just a reference, not a
              >>reference to const object.
              >>>
              >>is it because to allow for expressions such as
              >>>
              >>(x = y) + z;
              >>where x, y, z are of type Test ?
              >>>
              >>What would happen if we allowed "const Test &" as the return type of
              >>Test::operato r=( ) ?
              >
              Erik Wikström <Erik-wikstrom@telia. comwrites:
              >I would say it is because there is no reason to return a const reference
              >(since the object referred to is not const) and it does allow us to do
              >some things that a const reference would not. Your example above "(x =
              >y) + z;", however, should work even with a const reference,
              >
              How come? There is no "operator=(cons t Test&)const", so how could it
              work?
              Because the plus operator should take const references as arguments and
              be declared as const.

              class Foo
              {
              public:
              const Foo& operator=(const Foo& rhs) { return *this; }
              Foo operator+(const Foo& rhs) const { return Foo(); }
              };

              int main()
              {
              Foo a, b, c;

              Foo d = (a = b) + c;

              Foo e = a + b;
              }
              >the
              >following would not "(x = y) += z;", but on the other hand you should
              >probably write such code in the first place. Notice also that the other
              >unary operators, such as +=, *=, etc., return a non-const reference.
              >
              Those are not unary operators and they return the type you specify which
              should be const reference.
              Sorry, yes they are not unary operators, I meant assignments operators.
              And of course they return whatever type you want them to return, but
              they *should* return a non-const reference to themselves (or a type
              which is convertible to that).
              Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
              = c" to work and thus they should not work. Operator overloading is not
              for creating new syntax.
              I expect them to work, the most important thing when overloading
              operators is to keep the semantics sane, which usually means that it
              should be compatible with the semantics of built-in types. Of course it
              is really bad style to actually use such code, but it should work.


              --
              Erik Wikström

              Comment

              • Michal Nazarewicz

                #8
                Re: assignment operator

                >Erik Wikström <Erik-wikstrom@telia. comwrites:
                >>I would say it is because there is no reason to return a const reference
                >>(since the object referred to is not const) and it does allow us to do
                >>some things that a const reference would not. Your example above "(x =
                >>y) + z;", however, should work even with a const reference,
                On 2007-09-23 13:32, Michal Nazarewicz wrote:
                >How come? There is no "operator=(cons t Test&)const", so how could it
                >work?
                Erik Wikström <Erik-wikstrom@telia. comwrites:
                Because the plus operator should take const references as arguments and
                be declared as const.
                Ah... Sorry... You are of course right.

                --
                Best regards, _ _
                .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
                ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
                ooo +--<mina86*tlen.pl >--<jid:mina86*jab ber.org>--ooO--(_)--Ooo--

                Comment

                • Michal Nazarewicz

                  #9
                  Re: assignment operator

                  >Erik Wikström <Erik-wikstrom@telia. comwrites:
                  >>the
                  >>following would not "(x = y) += z;", but on the other hand you should
                  >>probably write such code in the first place. Notice also that the other
                  >>unary operators, such as +=, *=, etc., return a non-const reference.
                  Michal Nazarewicz wrote:
                  >Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
                  >= c" to work and thus they should not work.
                  Kai-Uwe Bux <jkherciueh@gmx .netwrites:
                  Those programmers expect wrongly. These expressions work just fine for built
                  in types:
                  Everyday you learn something new. I wasn't aware that such think is
                  possible in C++ (it's not in C from what I know). Thanks for pointing
                  this out.

                  --
                  Best regards, _ _
                  .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
                  ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
                  ooo +--<mina86*tlen.pl >--<jid:mina86*jab ber.org>--ooO--(_)--Ooo--

                  Comment

                  • James Kanze

                    #10
                    Re: assignment operator

                    On Sep 23, 12:28 pm, "subramanian10. ..@yahoo.com, India"
                    <subramanian10. ..@yahoo.comwro te:
                    For a class Test, we write the assignment operator as
                    Test & Test::operator= (const Test & rhs);
                    instead of
                    const Test & Test::operator= (const Test & rhs);
                    that is, the return type of operator=( ) is just a reference, not a
                    reference to const object.
                    is it because to allow for expressions such as
                    (x = y) + z;
                    where x, y, z are of type Test ?
                    What would happen if we allowed "const Test &" as the return type of
                    Test::operator= ( ) ?
                    The only real reason for the return value to be non-const is
                    because that is what the built-in operator= does, so applying
                    the principle of least surprise...

                    I believe that the standard "justificat ion" is to allow things
                    like:

                    class D
                    {
                    public:
                    C& D::setX( C newValue )
                    {
                    return myC = newValue ;
                    }

                    private:
                    C myC ;
                    } ;

                    I'll admit that I'm not totally convinced; a return statement
                    should return a value, and not modify some value. My operator=
                    returned const references for a long time, and this never caused
                    any problems in any of the code I had to maintain. But since
                    the built-in operator= evaluates to a non-const lvalue, I've
                    adopted the non-const reference, just to be as much like it as
                    possible.

                    --
                    James Kanze (GABI Software) email:james.kan ze@gmail.com
                    Conseils en informatique orientée objet/
                    Beratung in objektorientier ter Datenverarbeitu ng
                    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                    Comment

                    • James Kanze

                      #11
                      Re: assignment operator

                      On Sep 23, 4:09 pm, Michal Nazarewicz <min...@tlen.pl wrote:
                      Erik Wikström <Erik-wikst...@telia. comwrites:
                      >the
                      >following would not "(x = y) += z;", but on the other hand you should
                      >probably write such code in the first place. Notice also that the other
                      >unary operators, such as +=, *=, etc., return a non-const reference.
                      Michal Nazarewicz wrote:
                      Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
                      = c" to work and thus they should not work.
                      Kai-Uwe Bux <jkherci...@gmx .netwrites:
                      Those programmers expect wrongly. These expressions work
                      just fine for built in types:
                      Everyday you learn something new. I wasn't aware that such think is
                      possible in C++ (it's not in C from what I know). Thanks for pointing
                      this out.
                      It's a significant difference. In C, none of the assignment
                      operators, nor increment nor decrement, result in lvalues. In
                      C++, all of the assignment operators, along with pre-increment
                      and pre-decrement, result in lvalues---in general, if an
                      expression requires an lvalue, and the value of that expression
                      is the value of the lvalue, after evaluation of the expression,
                      the expression results in an lvalue in C++.

                      --
                      James Kanze (GABI Software) email:james.kan ze@gmail.com
                      Conseils en informatique orientée objet/
                      Beratung in objektorientier ter Datenverarbeitu ng
                      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                      Comment

                      • James Kanze

                        #12
                        Re: assignment operator

                        On Sep 23, 2:30 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
                        On 2007-09-23 13:32, Michal Nazarewicz wrote:
                        [...]
                        Programmers don't expect expressions such as "(a = b) = c" or "(a += b)
                        = c" to work and thus they should not work. Operator overloading is not
                        for creating new syntax.
                        I expect them to work, the most important thing when overloading
                        operators is to keep the semantics sane, which usually means that it
                        should be compatible with the semantics of built-in types. Of course it
                        is really bad style to actually use such code, but it should work.
                        The above will *not* work with the built-in operators. It
                        results in undefined behavior, due to an object being modified
                        twice without an intervening sequence point.

                        C++ has different rules than C regarding lvalues. I rather
                        suspect that this is related to the introduction of references
                        (which make lvalue-ness far more directly observable). In C++,
                        you can write:

                        int a, b ;
                        int& r = (a = b) ;
                        int* p = &(a = b) ;

                        In C, the second line, of course, is irrelevant, and the third
                        line is illegal.

                        Note that something like the second line will occur if you write
                        something like:
                        a = b + (c = d) ;
                        for a user defined type. Since this sort of thing is perfectly
                        legal for e.g. int or double, it does seem like the language
                        should allow it for user defined types as well.

                        --
                        James Kanze (GABI Software) email:james.kan ze@gmail.com
                        Conseils en informatique orientée objet/
                        Beratung in objektorientier ter Datenverarbeitu ng
                        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                        Comment

                        • Andrew Koenig

                          #13
                          Re: assignment operator

                          "James Kanze" <james.kanze@gm ail.comwrote in message
                          news:1190576740 .459023.306820@ k79g2000hse.goo glegroups.com.. .
                          On Sep 23, 2:30 pm, Erik Wikström <Erik-wikst...@telia. comwrote:
                          C++ has different rules than C regarding lvalues. I rather
                          < suspect that this is related to the introduction of references
                          < (which make lvalue-ness far more directly observable). In C++,
                          < you can write:

                          int a, b ;
                          int& r = (a = b) ;
                          int* p = &(a = b) ;
                          In C, the second line, of course, is irrelevant, and the third
                          line is illegal.
                          You're pretty much right about the reason--I happen to have been there when
                          the issue first came up, so I know the history.

                          Here's the key question: You have a fragment of code that looks like this:

                          // ...
                          x = y;
                          return x;

                          Can you replace that code with

                          return x=y;

                          without changing the meaning of the program?

                          In C, the answer is always yes. In C++, the situation is trickier:

                          int& foo(int& x, int y)
                          {
                          x = y;
                          return x;
                          }

                          If = were defined on int objects the same way as in C, then changing this
                          function to

                          int& foo(int& x, int y)
                          {
                          return x = y;
                          }

                          would cause it to stop compiling, because in C, = yields an rvalue.

                          So the fact that a function can potentially return a reference makes it
                          necessary to redefine = to return an value.

                          It turns out that this redefinition is still compatible with C, because it
                          is impossible to write a C program that is capable of detecting whether =
                          returns an lvalue or an rvalue.

                          Once the built-in = operator returns an lvalue, it makes sense for
                          user-defined ones to behave similarly.

                          Incidentally, the same reasoning applies to ++x, --x, and x?y:z.


                          Comment

                          Working...