3

How can I overload the operator& in C++? I've tried this:

#ifndef OBJECT_H
#define OBJECT_H
#include<cstdlib>
#include<iostream>

namespace TestNS{

    class Object{
    private:
        int ptrCount;
    public: 
        Object(): ptrCount(1){           
            std::cout << "Object created." << std::endl;
        }
        void *operator new(size_t size);
        void operator delete(void *p);
        Object *operator& (Object obj);
    };

    void *Object::operator new(size_t size){            
            std::cout << "Pointer created through the 'new' operator." << std::endl; 
            return malloc(size);
        }

    void Object::operator delete(void *p){
            Object * x = (Object *) p;
            if (!x->ptrCount){
                free(x);
                std::cout << "Object erased." << std::endl;
            }
            else{
                std::cout << "Object NOT erased. The " << x->ptrCount << "references are exist." 
                    << std::endl;
            }
        }
    
    Object *Object::operator& (Object obj){
            ++(obj.ptrCount);
            std::cout << "Counter is increased." << std::endl;
            return &obj;
        }
}
#endif

Tne main function:

#include<iostream>
#include"Object.h"

namespace AB = TestNS;

int main(int argc, char **argv){
    AB::Object obj1;
    AB::Object *ptrObj3 = &obj1; // the operator& wasn't called.
    AB::Object *ptrObj4 = &obj1; // the operator& wasn't called.

    AB::Object *obj2ptr = new AB::Object();
}

The output result:

Object created.

Pointer created through the 'new' operator.

Object created.

My operator& wasn't called. Why?

Community
  • 1
  • 1
Andrey Bushman
  • 11,712
  • 17
  • 87
  • 182
  • You're doing this: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – chris Apr 23 '13 at 12:29
  • 4
    Try `AB::Object *ptrObj5 = obj1 & obj1;` and you'll know why. – johnchen902 Apr 23 '13 at 12:31
  • 3
    I think what you're doing here is a very bad idea. operator& for reference counting will lead to grief. – Sebastian Redl Apr 23 '13 at 12:33
  • Because it's such an incomplete solution. Especially if you return a raw pointer from the operator. At the very least, return something that decreases the reference count on destruction. But the thing about overloading the address-of operator is that it makes it annoying to work with the object. Also, what about normal references instead of pointers? I can just say Object& or = *somePointer, and you can't keep track of that. Basically, there's so many holes in this scheme to slip through that you'll spend all your time debugging reference count errors. – Sebastian Redl Apr 23 '13 at 12:39
  • @Sebastian Redl Are exist the reliable method for the preventing of memory leak? – Andrey Bushman Apr 23 '13 at 12:46
  • That is a massive can of worms. Use best practices. Try to use objects on the stack instead of on the heap whenever possible. Use smart pointers. Be disciplined. What doesn't work is trying to create the kind of uber-object you're working on. If all else fails, use a garbage-collected language ;) – Sebastian Redl Apr 23 '13 at 12:49
  • 1
    First, overloading unary `&` is often a bad idea. If you must, your design is flawed -- `&` should return a smart-pointer-to-`this` based off of intrusive reference counting (either `std::enable_shared_from_this`, or a custom solution). Do not overload operator `new` and `delete`, that isn't what those overloads are for -- instead, hide the constructor and provide `static smart_ptr CreatePtr( Args&&... args )` wrappers. Note that no garbage-collected object can exist in automatic storage, or within another non-garbage collected object, so this design causes performance hits. – Yakk - Adam Nevraumont Apr 23 '13 at 13:01

2 Answers2

14

You are currently overloading the binary & operator (i.e. bitwise AND). To overload the unary & operator, your function should take no arguments. The object it applies to is that pointed to by this.

Object *Object::operator& (){
    ++(this->ptrCount);
    std::cout << "Counter is increased." << std::endl;
    return this;
}
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
2

The sftrabbit answer is correct about syntax, but beware that what you are doing with new and delete is not congruent.

the new and delete operator work on raw memory, not on constructed object.

When you do A* p = new A ...

  • operator new is called and ...
  • the object A constructor is than called over the returned memory address and ...
  • finally the address is converted into A* and given to p.

Similarly, when you do delete p ...

  • The A destructor is called and...
  • The memory address is given to operator delete to be given back to the system.

In both the situation the state of A object instance (the value of its members) is undefined:

  • inside the operator new whatever thing you do, will be overwritten by the subsequent constructor call. In case the constructor does not initialize something, the standard says it's value is undefined (and not granted to be the same you can set in new).
  • inside the operator delete whatever thing you do is done on an already dead object (and what you found inside it is not granted to be the "last live state".

In any case the object dies when you call delete. You cannot "save it from dead" during operator delete (that's called after destruction). It's purpose is to place the tombstone, not to reanimate the cadaver.

Community
  • 1
  • 1
Emilio Garavaglia
  • 20,229
  • 2
  • 46
  • 63