如何通过“新”运算符阻止类分配? (我想确保我的RAII类总是在堆栈上分配。)

时间:2008-09-24 01:18:46

标签: c++ operator-overloading c++-faq

我想确保我的RAII类总是在堆栈上分配。

如何阻止通过'new'运算符分配类?

4 个答案:

答案 0 :(得分:51)

您需要做的就是声明类'new operator 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;
};

相关问题: Is it possible to prevent stack allocation of an object and only allow it to be instiated with ‘new’?

答案 1 :(得分:6)

我不相信你的动机。

有充分的理由在免费商店创建RAII课程。

例如,我有一个RAII锁类。我有一条通过代码的路径,只有在某些条件成立时才需要锁定(它是一个视频播放器,我只需要在渲染循环期间保持锁定,如果我有一个视频加载和播放;如果没有加载,我不需要它)。因此,在free store上创建锁(使用scoped_ptr / auto_ptr)的能力非常有用;它允许我使用相同的代码路径,无论我是否必须取出锁定。

即。像这样的东西:

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

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

答案 2 :(得分:2)

<强> @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(); 

答案 3 :(得分:0)

在我的特殊情况下,如果不需要锁定,则互斥锁甚至不存在,所以我认为这种方法更难以适应。

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