代码之家  ›  专栏  ›  技术社区  ›  Kevin

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

  •  40
  • Kevin  · 技术社区  · 17 年前

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

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

    4 回复  |  直到 9 年前
        1
  •  52
  •   Kevin    9 年前

    您只需声明类“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’?

        2
  •  6
  •   DrPizza    17 年前

    我不相信你的动机。

    有充分的理由在免费商店上创建raii类。

    例如,我有一个raii lock类。我有一条通过代码的路径,只有在某些条件成立时才需要锁(它是一个视频播放器,我只需要在渲染循环期间持有锁,如果我已经加载并播放了视频;如果没有加载任何内容,我不需要它)。因此,在自由存储上创建锁的能力(使用作用域为/auto-ptr)非常有用;它允许我使用相同的代码路径,而不管是否需要取出锁。

    也就是说,像这样的事情:

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

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

        3
  •  2
  •   Kevin    17 年前

    @ 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(); 
    
        4
  •  0
  •   DrPizza    17 年前

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

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