1

Could someone please explain the difference to me in very small words? I have never understood this and am very confused in my current project. What I am trying to do is fix this code:

const Multinumber& Pairs::operator+(const Multinumber &rhs) const
{
    const Pairs &_rhs = dynamic_cast<const Pairs &>(rhs);
    Pairs toreturn(_rhs.X_value+X_value,_rhs.Y_value+Y_value);
    return toreturn; //reference to local variable? fix this?
}

Now my compiler tells me that this is a reference to a local variable, but it won't let me turn toreturn into a pointer, because they are somehow different from references. And then, I am also working on a set class, which is supposed to hold references or pointers to objects of an abstract class. I am totally confused. Any help would be much appreciated.

jwueller
  • 30,582
  • 4
  • 66
  • 70
  • 1
    http://stackoverflow.com/questions/57483/difference-between-pointer-variable-and-reference-variable-in-c In your case, a reference is an alias, and refers to some address. However, you refer to `toreturn`, which is created locally, and then you attempt to return its reference, even though `toreturn`'s lifetime ends when the function returns. – wkl Nov 25 '10 at 22:51
  • you can always make toreturn `static` but it doesn't seem to be a good idea either ... – erjot Nov 25 '10 at 22:58

3 Answers3

2

First, your signature is wrong. It should be:

Multinumber Pairs::operator+(const Multinumber &rhs) const;

operator+ should return a new object, not a reference to either argument.

As for the difference between references and pointers, this detailed question right here on SO. It covers all the basics, and the some.

Community
  • 1
  • 1
André Caron
  • 44,541
  • 12
  • 67
  • 125
  • Actually, your signature is wrong too. It should be `Multinumber operator+(const Multinumber& lhs, const Multinumber& rhs)`, or possibly `const Multinumber operator+(const Multinumber& lhs, const Multinumber& rhs)`. – wilhelmtell Nov 25 '10 at 22:59
  • 1
    @wilhelmtell You declared function, @André declared method – Gaim Nov 25 '10 at 23:03
  • @Gaim Yes. Because `operator+()` should be a free function. – wilhelmtell Nov 25 '10 at 23:06
  • @wilhelmtell it needn't. It can be redefined as method. It is one of two options – Gaim Nov 25 '10 at 23:15
  • @wilhelmtell, it really doesn't matter one way or the other, especially since they are the same type (and so there is no issue of implementing one asymmetric addition in terms of the other). I happen to find it easier to navigate the auto-generated documentation when it is implemented as member. It's purely a matter of style and taste. – Michael Aaron Safyan Nov 25 '10 at 23:15
  • 2
    @Gaim @MichaelAaronSafyan it's not a matter of style and it is most certainly not a matter of taste. It's a matter of functionality. If `Multinumber` is convertible from, say, an int (i.e. `Multinumber` has a constructor that takes an int) then the expression `1 + Multinumber()` will work _only_ if `operator+()` is a free function. Also, if `operator+()` returns a non-const then the expression `Multinumber() + Multinumber() = Multinumber()` is valid. Whether this is useful or correct is arguable and perhaps context-dependent. – wilhelmtell Nov 25 '10 at 23:28
  • I'm using the skeleton code that my professor provided. That function signature was part of the code. I can be reasonably certain that the signature is accurate. Is there any other possibility? –  Nov 25 '10 at 23:34
  • @Ross: no, you cannot assume it is accurate. You can report this issue to your professor, with non-compiling sample, and explain to him why you understand it is wrong. Then, ask for permission to change it. – André Caron Nov 26 '10 at 00:01
  • @wilhelmtell: I generally implement it as a free function for the same reasons, and also because it makes one less function with access to private members. However, I proposed that change here because 1) it is the minimal correct change that will make it work; and 2) it puts emphasis on what is being done wrong. – André Caron Nov 26 '10 at 00:02
  • @wilhelmtell: amusing logic re member/non-member use: emphatically functionality not taste + a qualification worded like an example ;-). You're right anyway: `X::operator Y() const` won't match as lhs of `Y::operator+(Y)`. non-member isn't a point of maintenance when introducing implicit constructors. + as André says, non-member doesn't implicitly have access to protected/private members - a better default. Both pro & con: the non-member clutters the interface less - making it easier to understand the core class functionality, but there's less of the effective API localised in the class. – Tony Delroy Nov 26 '10 at 02:45
1

You do seem very confused :) Ok, so:

Essentially, a pointer is just a variable that stores the address of another variable. For instance, suppose I have an int called i, I can store its address in a pointer p:

int i = 23;
int *p = &i;    // p has type int* (pointer to int) and stores &i (the address of i)

If I then want to change the thing it points to (i.e. the variable whose address it stores), I just assign to *p -- this is the syntax used to denote the thing pointed to. In this case, *p refers to i. Thus:

*p = 9;     // sets i to 9 (since *p is i)

I can reseat the pointer (i.e. make it point to something else) just by assigning to p, i.e.

int j = 84;
p = &j;     // store j's address in p, overwriting what was there before (i.e. i's address)
*p = 18;        // sets j to 18 (since *p is now j)

Now, a reference is slightly different. A reference creates an alias for a variable:

int i = 23;
int& r = i;     // r has type int& (reference to int) and refers to i

Note that references may be implemented in terms of pointers (or they may not, particularly when the compiler starts optimizing things), but that's irrelevant from the programming perspective -- all that matters to us here is the way the language works.

If you want to change the thing referred to (i.e. i in this case), you just do:

r = 9;      // sets i to 9 (since r is an alias for i)

Unlike pointers, references cannot be reseated. As just shown, assigning to r changes the thing you're referring to (i), not the reference itself. Furthermore, because references cannot be reseated, they must be initialized immediately. This is not the case with pointers. In other words:

int *p;     // legal
int& r;     // bad

One final basic difference is that pointers can be NULL, indicating that they are not pointing to anything. This just means they contain the address 0. References must always refer to an actual object. This difference can be important to implementers, because they can then use pointers to implement a Maybe type, i.e. if the pointer is not NULL, then make use of the pointed-to object, otherwise do something else. They can't do the same thing with references.

Hope that's clear as regards pointers vs. references!


Now, regarding your operator+ -- the purpose of an addition operator is to add two objects and return a new object representing their sum. So if I had a 2D vector type, I might write an operator+ for it as follows:

Vec2 operator+(const Vec2& lhs, const Vec2& rhs)
{
    return Vec2(lhs.x+rhs.x, lhs.y+rhs.y);
}

In your code, you are trying to return a local object toreturn by reference -- this doesn't work, because toreturn ceases to exist at the end of the operator. Instead, you should return by value here. Incidentally, you would encounter the same problem if you tried to return a pointer, e.g.

Vec2* operator+(const Vec2& lhs, const Vec2& rhs)
{
    Vec2 result(lhs.x+rhs.x, lhs.y+rhs.y);
    return &result; // bad!
}

In that code, result ceases to exist at the end of the operator, so the pointer you return would end up pointing to an invalid location. Bottom line -- don't try anything fancy, return by value in this sort of situation.

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
  • Thanks! Anyway, my problem with returning by value is that I have to return an object of type Multinumber because I am using polymorphism and the base class's operator+ is defined as returning a Multinumber. Complex inherits Multinumber. And Multinumber is virtual so I have to return by reference rather than value. –  Nov 26 '10 at 15:46
0

Pointer has some address where the object is. And the reference is as the alias for the pointer and it means that you don't have to dereference it. But the usage is similar - don't copy objects, only work with the origin.

You have the variable toreturn as a local variable which means that the compiler generates the destructor for this object at the end of method. So you are trying to return destroyed object.

Gaim
  • 6,734
  • 4
  • 38
  • 58