Reader Q&A: How can I prevent a type from being instantiated on the stack?

Anubhav asked:

An interesting question has come up in our project while debating operator new as a class member function. Specifically, the question is about whether such a class should be allowed to be instantiated on stack. The understanding is that a class providing its own operator new would likely have special layout considerations which would not be met if the object of such a class is instantiated locally.

The class specific operator new is used when allocating on the heap, but objects can still be allocated on the stack. The only way I know to prevent an object from being instantiated on the stack is by forcing creation through a factory function that always allocates on the heap, for example:

#include <memory>

class X {
// make all ctors private
X(const X&);
// and any other ctors go here

// Factory function (or it could be a nonmember friend)
static auto make( /*…*/ ) { return std::unique_ptr<X>(new X( /*…*/ )); }

// the usual public member functions go here

int main()
X x; // error
auto x2 = X::make(); // ok

9 thoughts on “Reader Q&A: How can I prevent a type from being instantiated on the stack?

  1. But std::make_unique also requires access to the constructor, right? X::make could create the unique_ptr manually instead.

  2. @mttpd: The protected destructor solution also works, but it’s a C++98 idiom that’s now inferior because it requires using a custom ‘deleter’ function that is possible, but less natural and idiomatic in modern C++, to use together with unique_ptr and shared_ptr.

    @Petter: Good point, thanks. Fixed.

  3. @Good point, thanks. Fixed.

    But this also gives up on the perf and memory layout advantages of std::make_shared… In library code this could be premature pessimisation. What about:

    class X
    //make all ctors private

    struct PrivateConstructionTag {};

    static auto make( /*…*/ ) { return std::make_shared( /*…*/ PrivateConstructionTag()); }

    I’m using this pattern in my library code. Is this the best solution?

  4. Correction:

    	X(..., PrivateConstructionTag);

    should be

    	X(..., PrivateConstructionTag);
  5. Hi. Does std::make_unique have the same problems with the private constructor pattern as std::make_sharedcode> have? I.e. that it is not portably possible to make std::make_shared a friend of X in the example. What is the preferred way to solve this problem? Is the use of the PrivateConstructorTag the only way?

  6. If


    is the plan anyway, then deriving from


    may be adequate. No?

  7. @Grout: Deriving from enable_shared_from_this doesn’t actually block compilation of code that instantiates the object on the stack. Nor does it block compilation of new Foo(). I have found the PrivateConstructorTag to be the best way to ensure that a class that inherits from enable_shared_from_this is only constructed with make_shared().

  8. My idea is a wrapper around. Is there any issues?

    template <typename Wrapped> class HeapOnly 
    	typedef std::unique_ptr<Wrapped> TPtr;
    	typedef const std::unique_ptr<Wrapped> TConstPtr;
        TPtr m_wrapped;
        operator TPtr&      ()       { return m_wrapped; }
        operator TConstPtr& () const { return m_wrapped; }
        HeapOnly(/* sorry, but I'm unfamiliar with variable templates so far...*/) 
            : m_wrapped( std::make_unique<Wrapped>(/*...*/) )
    class A {
        A() {} // private ctors
    	// ...
        // ... others 
        friend class HeapOnly<A>;
    void f()
         HeapOnly<A> compilationOk;
         A compilationError;

Comments are closed.