Hans
Hans

Reputation: 1379

C++ referencing operator in declaration

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.

Upvotes: 1

Views: 982

Answers (4)

R Sahu
R Sahu

Reputation: 206577

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;

Upvotes: 1

6EQUJ5
6EQUJ5

Reputation: 3302

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*/
} 

Upvotes: 3

Brian Bi
Brian Bi

Reputation: 119164

The token & has three distinct meanings in C++, two of which are inherited from C, and one of which is not.

  1. It's the bitwise AND operator (unless overloaded).
  2. 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.
  3. 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.

Upvotes: 4

Pranit Kothari
Pranit Kothari

Reputation: 9841

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.

Upvotes: -1

Related Questions