2

Is it possible to overload the operator new() to have a different return value than void*?

I have two structures:

One structure (A) just holds data and what not.

The second structure (B) is built to act like a pointer to the first:

struct A;

struct B
{

private:

    A* ptr;

public:

    A& operator*() { return (*ptr); };
    A& operator->() { return (*ptr); };

};


struct A
{
    int data;

    B operator&() { B ret;  ret.ptr = this; return ret; };
};

The idea is as simple as this. I don't want any external classes handling pointers to A, not directly.

However, I do want them to be able to create instances of A. Is there a way to override A's new operator to return an instance of B? Nevermind right now the safety concerns, and handling delete, this is just a simple, reduced example to explain my problem.

Serge
  • 1,974
  • 6
  • 21
  • 33
  • Wouldn't a private constructor do the job here? – Jasper Oct 30 '12 at 18:28
  • 3
    Overriding operator `new` is almost always the _wrong_ thing to do. Why not instead make the constructor and destructor private, and have a factory method that returns a smart pointer wrapping a new class instance? – Rook Oct 30 '12 at 18:29
  • @Jasper True, that makes sense; However, in cases of private constructors, what is the typical implementation for creating a new copy? A factory? – Serge Oct 30 '12 at 18:29
  • @Rook actually, I'm already overloading new so I can make sure all instances of the struct are in a memory pool... But, otherwise, yeah, I know what you mean V_V – Serge Oct 30 '12 at 18:31
  • If you want your structs placed in a specially managed memory segment then overriding `new` operator might be appropriate. You should use a (placement new operator)[http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new] – πάντα ῥεῖ Oct 30 '12 at 18:36
  • What about having B() constructor create a new instance of A, and then making A a nested class? – imreal Oct 30 '12 at 18:36
  • @g-makulik I did that once before; however, by placing it in the new operator, I make all the memory management internal to the class, rather than external to something that's creating a copy of it. I thought it might look cleaner that way. But, given I'm making a factory for this all now, it might not be exactly the case any more. – Serge Oct 30 '12 at 18:39
  • @Nick would be possible, except that all my instances of A need to persist, while most of my instances of B are rather temporary. B is just for interfacing with some A's when I need to. – Serge Oct 30 '12 at 18:41
  • @Rook why do you say overriding `operator new` is almost always wrong?? in many situations overriding that operator make life so much better! – BigBoss Oct 30 '12 at 18:42
  • How can A persist and B be temporary if no one else can handle A? How do you keep a hold of an A instance after the B dies? Is there some kind of container? – imreal Oct 30 '12 at 18:44
  • @Serge Factory might be what you want, though what you're showing for class `A` looks like a smart pointer specialized for `B`. BigBoss' answer clearly explains, that it makes no sense to return other value than `void*` since the overload solely is responsible for the memory allocation and thus can't return typed (corretly initialized) pointers. – πάντα ῥεῖ Oct 30 '12 at 18:45
  • @BigBoss because it _is_ almost always wrong. Please note the "almost", however. I do not believe that there are "many" situations where it is a desirable thing to do. You should be very circumspect about changing the semantics of the language, when a perfectly reasonable and unambiguous alternative is to use a factory method and private constructor/destructor as mentioned above. – Rook Oct 30 '12 at 18:53
  • `struct A { static B Create() { return B(new A); private: A(); }` is a simple way to "hide" the ability to create an `A` directly (via new), and only allow you to create `B`'s that wrap `A`s. Clients call `A::Create()`. Create need not be a static method of A. – Yakk - Adam Nevraumont Oct 30 '12 at 19:11
  • @Rook As you can see in my answer, `operator new` is just responsible for memory allocation, not for class creation and when you are working with devices, normal memory can't serve you well or you may want your memory to have certain alignment, or in most common case you want to allocate memory of your class from a pool since it will frequently allocated and using this technique you want to reduce allocation penalty and memory fragmentation and ... . we do not want to and we can't change class creation with `new`, just how its memory allocated – BigBoss Oct 30 '12 at 19:11
  • Thanks, everyone, for all the advice! – Serge Oct 30 '12 at 19:25

2 Answers2

3

No.

3.7.4.1 Allocation functions:

... The return type shall be void*. ...

As BigBoss says this is because the new operator calls operator new and expects it to have a certain return type.

bames53
  • 86,085
  • 15
  • 179
  • 244
2

Operator new is only responsible to allocate memory for the class and then C++ internally call constructor to initialize that memory, so if you want to override something to new A result in a B, then you should override C++!

Instead you may have:

struct A {
private
    friend struct B;
    A() {}
};
struct B {
    static B new_A() {return B(new A());}
}
BigBoss
  • 6,904
  • 2
  • 23
  • 38