防止对象的堆栈分配而仅允许使用“新”实例化它?

是否可以防止对象的堆栈分配,而只允许在堆上使用“ new”来初始化它?

Jon Stewart asked 2020-01-29T02:21:00Z
6个解决方案
83 votes

一种执行此操作的方法是将构造函数设为私有,并且仅允许通过返回指针的静态方法进行构造。 例如:

class Foo
{
public:
    ~Foo();
    static Foo* createFoo()
    {
        return new Foo();
    }
private:
    Foo();
    Foo(const Foo&);
    Foo& operator=(const Foo&);
};
Daemin answered 2020-01-29T02:21:13Z
18 votes

对于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 answered 2020-01-29T02:21:33Z
11 votes

您可以使构造函数private,然后提供public静态工厂方法来创建对象。

Jason Cohen answered 2020-01-29T02:21:54Z
5 votes

以下允许公共构造函数,并将通过在运行时抛出来停止堆栈分配。 注意thread_local是C ++ 11关键字。

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 answered 2020-01-29T02:22:15Z
0 votes

在C ++ 20中使用销毁运算符delete应该可以实现此功能,请参见p0722r3。

#include <new>

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

请注意,私有析构函数可防止将其用于动态存储持续时间以外的任何其他时间。 但是销毁操作符delete允许通过delete表达式销毁它(因为在这种情况下delete表达式不会隐式调用析构函数)。

cmeerw answered 2020-01-29T02:22:39Z
-1 votes

您可以创建一个为对象提供抽象接口的头文件,以及返回指向在堆上创建的对象的指针的工厂函数。

// 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 answered 2020-01-29T02:23:00Z
translate from https://stackoverflow.com:/questions/124880/is-it-possible-to-prevent-stack-allocation-of-an-object-and-only-allow-it-to-be