我如何防止通过'new'运算符分配一个类? (我想确保RAII类始终分配在堆栈上。)

我想确保RAII类始终分配在堆栈上。

如何防止通过“新”运算符分配类?

Kevin asked 2020-07-23T18:08:16Z
4个解决方案
54 votes

您需要做的就是声明该类的新运算符为private:

class X
{
    private: 
      // Prevent heap allocation
      void * operator new   (size_t);
      void * operator new[] (size_t);
      void   operator delete   (void *);
      void   operator delete[] (void*);

    // ...
    // The rest of the implementation for X
    // ...
};  

将“ operator new”设置为私有可有效防止类外部的代码使用“ new”创建X的实例。

要完成操作,您应该隐藏“ operator delete”和两个运算符的数组版本。

从C ++ 11开始,您还可以显式删除函数:

class X
{
// public, protected, private ... does not matter
    static void *operator new     (size_t) = delete;
    static void *operator new[]   (size_t) = delete;
    static void  operator delete  (void*)  = delete;
    static void  operator delete[](void*)  = delete;
};

相关问题:是否可以阻止对象的堆栈分配,而仅允许使用“ new”来初始化它?

Kevin answered 2020-07-23T18:08:50Z
6 votes

我不相信你的动机。

有充分的理由在免费商店中创建RAII类。

例如,我有一个RAII锁类。 我在代码中有一条路径,其中只有在满足某些条件的情况下才需要锁定(这是视频播放器,并且只有在加载并播放视频的情况下,才需要在渲染循环中保持锁定;如果没有加载, 我不需要)。 因此,在免费存储区(具有scoped_ptr / auto_ptr)上创建锁的功能非常有用; 它使我可以使用相同的代码路径,而不管是否必须取出锁。

即是这样的:

auto_ptr<lock> l;
if(needs_lock)
{
    l.reset(new lock(mtx));
}
render();

如果我只能在堆栈上创建锁,那我就不能做...。

DrPizza answered 2020-07-23T18:09:28Z
2 votes

@DrPizza:

这是一个有趣的观点。 请注意,尽管在某些情况下RAII习惯不一定是可选的。

无论如何,解决难题的更好方法是在锁构造函数中添加一个参数,该参数指示是否需要锁。 例如:

class optional_lock
{
    mutex& m;
    bool dolock;

public:
    optional_lock(mutex& m_, bool dolock_)
        : m(m_)
        , dolock(dolock_)
    {
        if (dolock) m.lock();
    }
    ~optional_lock()
    {
        if (dolock) m.unlock();
    }
};

然后,您可以编写:

optional_lock l(mtx, needs_lock);
render(); 
Kevin answered 2020-07-23T18:10:01Z
0 votes

在我的特殊情况下,如果不需要锁定,则互斥体甚至不存在,因此我认为这种方法将更难使用。

我想我真正要了解的是禁止在免费商店中创建这些对象的理由。

DrPizza answered 2020-07-23T18:10:26Z
translate from https://stackoverflow.com:/questions/124856/how-do-i-prevent-a-class-from-being-allocated-via-the-new-operator-id-like