0

How can I overload the new operator for a class type so that it allocates the memory on the stack instead of heap (basically so that the user doesn't have to call delete afterwards).

What about something like this:

class A{
    private:
        A(int i):
           this->i(i);
        {}
        A a;
        int i;

    public:
        void* operator new(size_t sz){
            a(12);
        }
};

Would the above solution work?

user965369
  • 5,413
  • 13
  • 33
  • 47
  • 2
    Umm you cannot there is a reason why there is both a stack and a heap. – JonH Oct 29 '12 at 14:30
  • 11
    What if the user not only didn't have to call `delete`, but didn't have to call `new` either? Wouldn't that be even better? – avakar Oct 29 '12 at 14:31
  • No I want to call a private constructor via the new operator. I am playing around and am trying to find some sort of work around. – user965369 Oct 29 '12 at 14:33
  • 2
    I think avakar is really on to something here. You should definitely go down that road =P – WhozCraig Oct 29 '12 at 14:33
  • 2
    @user965369: There is nothing about private constructors in your question. Can we have your actual use case in the question? – Lightness Races in Orbit Oct 29 '12 at 14:34
  • Note: technically there is placement `new`, but when it comes to delete-ing such objects... then `delete` no longer works (the destructor must be called explicitly), so don't. – Matthieu M. Oct 29 '12 at 14:35
  • Beyond using the `friend` keyword I don't think there is don't make it private. – andre Oct 29 '12 at 14:38
  • 1
    @user965369 If you must dynamic-allocate the object via private-constructor *and* you just aren't in a 'delete' sort of mood then (a) create a *class* static method to allocate the object for you using regular operator new(), and (b) contain it in a scope-level smart pointer. *Never* override operator new() unless you have a *damn* good reason (and this isn't one). – WhozCraig Oct 29 '12 at 14:38
  • Are you trying to stop someone using your class from allocating it on the heap? – andre Oct 29 '12 at 14:43
  • No reason, just interested in whether it can be done or not. – user965369 Oct 29 '12 at 14:44
  • 3
    The whole idea doesn't make sense, because, even if it could be done, it would violate the "expected behavior" of `new` - allocate an object whose lifetime is not tied to the current scope. Heck, if a caller wanted to allocate the object on the stack *would allocate it on the stack*, period! (s/on the stack/with automatic storage duration/) – Matteo Italia Oct 29 '12 at 14:48
  • I didn't ask whether it made sense or not I asked how to do it.. I know perfectly well that's its a stupid idea I was merely interested in hacking around. – user965369 Oct 29 '12 at 15:02
  • 1
    @Matteo: +1 for the obvious ;) – Lightness Races in Orbit Oct 29 '12 at 15:31

4 Answers4

9

Don't!

Use automatic storage...

The new operator is designed to implement dynamic allocation (what you are calling "on the heap") and, although you can provide your own allocator, as such you cannot twist it into obeying the scoping rules of objects of automatic storage duration (what you are calling "on the stack").

Instead, write:

MyType myobject;  // automatic storage duration

...or smart pointers...

Or, if you don't mind dynamic storage duration but only want to avoid later manual destruction, use smart pointers:

std::unique_ptr<MyType> myptr(new myobject());  // unique, dynamic storage duration
std::shared_ptr<MyType> myptr(new myobject());  // shared, dynamic storage duration

Both of these are found in C++11 (std::) and Boost (boost::).

... or placement new?

Another approach might be placement new but this is a dark and dangerous path to travel that I would certainly not recommend at this stage. Or, frankly, any stage... and you'd usually still need to do manual destruction. All you gain is using the keyword new, which seems pointless.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 3
    +1: I like the big fat **Don't!** ! – alestanis Oct 29 '12 at 14:44
  • 1
    just to add a link: [Why not use pointers for everything in C++?](http://stackoverflow.com/q/1064325/1025391) and [Proper stack and heap usage in C++?](http://stackoverflow.com/q/599308/1025391) – moooeeeep Oct 29 '12 at 14:51
2

I think the good answer here is:

Don't overload operator new.

If you still want to go through that road, you can look at this question.

If not, you can always use smart pointers or shared pointers to avoid users having to delete allocated memory.

Community
  • 1
  • 1
alestanis
  • 21,519
  • 4
  • 48
  • 67
1

It seems that you don't know what you're asking. By definition, the new operator allocates memory on the heap. To create an object on the stack, simply declare it as a local variable.

Looking at what you actually want to do, you said that the reason you thought this would be awesome would be:

basically so that the user doesn't have to call delete afterwards

And that functionality is implemented using smart pointers. I highly suggest that you invest your time learning those instead.

riwalk
  • 14,033
  • 6
  • 51
  • 68
1

Why not just automatic variable (it is "on stack" and does not need to call destructor manually:

int foo() {
  A a;
  int i;
  ...
  // don't need to call delete

}


To answer your question literally, there is placement new, which takes memory from user - so you can have this memory as automatic buffer:

  alignas(int) char buffer[sizeof(int)];
  int* p = new (buffer) int;
  //           ^^^^^^^^

For non POD object - you do not need to call delete - but you must call destructor by hand:

  class A { public: ~A(){} };
  alignas(A) char buffer[sizeof(At)];
  A* p = new (buffer) A;
  //         ^^^^^^^^
  p->~A();

alignas is new in C++11 - in C++03 you must deal with proper alignment somehow differently. Proper aligned memory must be returned from new - otherwise the behavior is undefined.

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • 3
    It is already in C++, it is "not using `new` when you don't need it", placement `new` in particular. Avoid placement new unless you really need it, especially if you use it in such a naive way (without checking the alignment of the buffer). – Matteo Italia Oct 29 '12 at 14:37
  • @MatteoItalia Added proper alignment to my answer. BTW, it seems that OP need it, why would OP post the question otherwise? – PiotrNycz Oct 29 '12 at 14:41
  • 1
    @PiotrNycz because he doesn't know what he wants or doesn't understand the dangers? – alestanis Oct 29 '12 at 14:44
  • If you ask to me, it seems that OP doesn't know what he's asking. If the whole point of this question is "basically so that the user doesn't have to call delete afterwards", placement new is not a solution, since you have to manually call the destructor. The logical solution would be for the caller to just allocate the object with automatic storage or with a smart pointer. – Matteo Italia Oct 29 '12 at 14:45
  • @MatteoItalia - true - after some consideration I put this as first answer. But just for next readers who might insist to implement this "on stack new" - I left the next part - that one does not need to implement something already implemented. – PiotrNycz Oct 29 '12 at 14:47