55

Is it possible to prevent stack allocation of an object and only allow it to be instiated with 'new' on the heap?

Jon Stewart
  • 393
  • 1
  • 4
  • 11
  • 2
    The reverse, which may also be interesting to readers: http://stackoverflow.com/questions/10985/how-to-prevent-an-object-being-created-on-the-heap – kevinarpe Aug 16 '16 at 14:36

6 Answers6

86

One way you could do this would be to make the constructors private and only allow construction through a static method that returns a pointer. For example:

class Foo
{
public:
    ~Foo();
    static Foo* createFoo()
    {
        return new Foo();
    }
private:
    Foo();
    Foo(const Foo&);
    Foo& operator=(const Foo&);
};
Dominik Grabiec
  • 10,315
  • 5
  • 39
  • 45
  • 14
    Or better still a static function that returns a std::unique_ptr. –  Oct 02 '12 at 20:43
  • **Related question:** [How do I prevent a class from being allocated via the 'new' operator? (I'd like to ensure my RAII class is always allocated on the stack.)](http://stackoverflow.com/questions/124856/how-do-i-prevent-a-class-from-being-allocated-via-the-new-operator-id-like) – Sergey M Dec 03 '13 at 23:22
  • But why make it unassignable too? – Deduplicator Feb 18 '15 at 22:34
  • 1
    Because if it's heap allocated then the object should not be copied, only its pointer should be copied. – Dominik Grabiec Feb 24 '15 at 03:57
25

In the case of C++11

class Foo
{
  public:
    ~Foo();
    static Foo* createFoo()
    {
        return new Foo();
    }

    Foo(const Foo &) = delete; // if needed, put as private
    Foo & operator=(const Foo &) = delete; // if needed, put as private
    Foo(Foo &&) = delete; // if needed, put as private
    Foo & operator=(Foo &&) = delete; // if needed, put as private

  private:
    Foo();
};
NebulaFox
  • 7,813
  • 9
  • 47
  • 65
  • 9
    As Scott Meyers stated in "Item 11: Prefer deleted functions to private undefined ones." his book "Effective Modern C++", it's better to declare deleted member functions `public`. --QUOTE-- "By convention, deleted functions are declared `public`, not `private`. There’s a reason for that. When client code tries to use a member function, C + + checks accessibility before deleted status. When client code tries to use a deleted `private` function, some compilers complain only about the function being `private`, even though the function’s accessibility doesn’t really affect whether it can be used." – Siu Ching Pong -Asuka Kenji- Mar 28 '15 at 15:10
  • 4
    --QUOTE-- "It’s worth bearing this in mind when revising legacy code to replace `private`-and-not-defined member functions with deleted ones, because making the new functions `public` will generally result in better error messages." – Siu Ching Pong -Asuka Kenji- Mar 28 '15 at 15:13
  • 2
    Must. Give. Moar. Up. Votes. – kevinarpe Aug 16 '16 at 14:57
12

You could make the constructor private, then provide a public static factory method to create the objects.

Jason Cohen
  • 81,399
  • 26
  • 107
  • 114
6

The following allows public constructors and will stop stack allocations by throwing at runtime. Note thread_local is a C++11 keyword.

class NoStackBase {
    static thread_local bool _heap;
protected:
    NoStackBase() {
        bool _stack = _heap;
        _heap = false;
        if (_stack)
            throw std::logic_error("heap allocations only");
    }
public:
    void* operator new(size_t size) throw (std::bad_alloc) { 
        _heap = true;
        return ::operator new(size);
    }
    void* operator new(size_t size, const std::nothrow_t& nothrow_value) throw () {
        _heap = true;
        return ::operator new(size, nothrow_value);
    }
    void* operator new(size_t size, void* ptr) throw () {
        _heap = true;
        return ::operator new(size, ptr);
    }
    void* operator new[](size_t size) throw (std::bad_alloc) {
        _heap = true;
        return ::operator new[](size);
    }
    void* operator new[](size_t size, const std::nothrow_t& nothrow_value) throw () {
        _heap = true;
        return ::operator new[](size, nothrow_value);
    }
    void* operator new[](size_t size, void* ptr) throw () {
        _heap = true;
        return ::operator new[](size, ptr);
    }
};

bool thread_local NoStackBase::_heap = false;
spiderlama
  • 1,539
  • 15
  • 10
  • I don't think you need `_stack` as a data member. Having it as a simple stack variable inside the `NoStackBase` constructor should do. – Paul J. Lucas Jan 25 '16 at 15:16
  • 1
    You also don't need to make the destructor `virtual`. Nobody can delete a derived class via a `NoStackBase` anyway. – Paul J. Lucas Jan 25 '16 at 15:48
  • since you explicitly call global operator new, I assume this won't call any custom operator overload those objects have defined (?), and forcing the use of those may be the motivating reason for this question – Joseph Garvin Jan 24 '20 at 16:00
2

This should be possible in C++20 using a destroying operator delete, see p0722r3.

#include <new>

class C
{
private:
  ~C() = default;
public:
  void operator delete(C *c, std::destroying_delete_t)
  {
    c->~C();
    ::operator delete(c);
  }
};

Note that the private destructor prevents it from being used for anything else than dynamic storage duration. But the destroying operator delete allows it to be destroyed via a delete expression (as the delete expression does not implicitly call the destructor in this case).

cmeerw
  • 7,176
  • 33
  • 27
-2

You could create a header file that provides an abstract interface for the object, and factory functions that return pointers to objects created on the heap.

// Header file

class IAbstract
{
    virtual void AbstractMethod() = 0;

public:
    virtual ~IAbstract();
};

IAbstract* CreateSubClassA();
IAbstract* CreateSubClassB();

// Source file

class SubClassA : public IAbstract
{
    void AbstractMethod() {}
};

class SubClassB : public IAbstract
{
    void AbstractMethod() {}
};

IAbstract* CreateSubClassA()
{
    return new SubClassA;
}

IAbstract* CreateSubClassB()
{
    return new SubClassB;
}
user18476
  • 39
  • 6