5

I wonder (just out of curiosity) why operator overloading isn't allowed in C++ for pointers. I mean something like this:

Vector2d* operator+(Vector2d* a, Vector2d* b) { return new Vector2d(a.x + b.x, a.y + b.y); }

Vector2d* a = new Vector2d(1, 1); 
Vector2d* b = new Vector2d(2, 2); 
Vector2d* c = a + b; 

Note how 'a + b' creates a new Vector object, but then copies only its address into 'c', without calling a copy constructor. So it would sort of solve the same problem that the new rvalue references solve. Also, as far as I know, it's pretty much equivalent to what happens when using operator overloading in C# (but I might be wrong here, I've never actually used C#), and why rvalue refs are not necessary in C#.

True, the rvalue reference solution is even better, as that allows stack-based objects, while this overloading would force all Vector2d objects to live on the heap, but still, it seems to be something that would have been easy to implement in compilers, possibly years before rvalue refs came around. And with custom allocators, it wouldn't even be that slow.

So is this only illegal because of the "least surprise" principle, or are there other reasons too?

imre
  • 1,667
  • 1
  • 14
  • 28
  • You can have pointers to stack-based objects just as well. – Luchian Grigore Apr 11 '13 at 08:19
  • What's the point of using `new` here for `a` and `b`? (`c` kind of makes sense, but it's still asking for trouble) – Pubby Apr 11 '13 at 08:21
  • Possible duplicate of http://stackoverflow.com/questions/6171630/why-isnt-operator-overloading-for-pointers-allowed-to-work – Saqlain Apr 11 '13 at 08:21
  • I think it's the prinicple of least surprise. For example operator- is defined on two pointers. So in your example you would have operator+ and operator- both defined but doing radically different things. – john Apr 11 '13 at 08:25
  • `new Vector2d` -- what is it, Java? – Abyx Apr 11 '13 at 08:36

2 Answers2

7

True, the rvalue reference solution is even better, as that allows stack-based objects, while this overloading would force all Vector2d objects to live on the heap, but still, it seems to be something that would have been easy to implement in compilers, possibly years before rvalue refs came around. And with custom allocators, it wouldn't even be that slow.

So is this only illegal because of the "least surprise" principle, or are there other reasons too?

  • It doesn't chain properly... what's a + b + c supposed to do, leak memory?
  • Pointer arithmetic already has a meaning in C++... it's useful for that to be consistent across types, otherwise e.g. algorithms wouldn't work properly on containers of your objects.
  • Returning something by value implies that object doesn't need clean up by the caller: if it uses free store (heap) to store actual data, it'll be deleting it automatically as necessary. Makes consistently robust memory usage easier.

Note how 'a + b' creates a new Vector object, but then copies only its address into 'c', without calling a copy constructor. So it would sort of solve the same problem that the new rvalue references solve.

The commonly implemented Return Value Optimisation also addressed this problem, helping the compiler arrange for construction of the return value directly into the caller's buffer.

Community
  • 1
  • 1
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Ah, pointer arithmetic, sure. I feel kinda stupid for not thinking of it myself. :) – imre Apr 11 '13 at 08:28
2

The main reason is because pointers already have a certain number of operators defined for them. If I have two variables a and b of type MyType, and I write a - b, then the reader knows that he has to look for an overload or an implicit conversion. If the variables have type MyType*, the reader would probably assume that a - b is pointer arithmetic; having it mean something else would be confusing, and would probably cause problems where ever arrays of MyType occur (including in the internals of std::vector).

Similar considerations apply to many of the other operators. The guideline in C++ is that you should be able to extend the language, but not change it. (And I know that unary & is an exception to this rule.)

With regards to C#, the languages are different. In C#, pointers aren't objects; there is no distinction between MyType and MyType*, and there are no operators on pointers. And C# doesn't use value semantics (usually), where as most objects in C++ will have value semantics, and will practically never be dynamically allocated. (If Vector2d means what it seems to mean, it should never be allocated dynamically in C++.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329