Is it possible to prevent stack allocation of an object and only allow it to be instantiated with 'new'?

后端 未结 6 1019
孤城傲影
孤城傲影 2020-11-30 03:44

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

相关标签:
6条回答
  • 2020-11-30 04:03

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

    0 讨论(0)
  • 2020-11-30 04:03

    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;
    }
    
    0 讨论(0)
  • 2020-11-30 04:05

    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;
    
    0 讨论(0)
  • 2020-11-30 04:08

    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&);
    };
    
    0 讨论(0)
  • 2020-11-30 04:15

    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).

    0 讨论(0)
  • 2020-11-30 04:27

    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();
    };
    
    0 讨论(0)
提交回复
热议问题