如何防止通过" new"运算符分配类? (我想确保RAII类始终分配在堆栈上。)
时间:2020-03-06 14:38:13 来源:igfitidea点击:
我想确保RAII类始终分配在堆栈上。
如何防止通过"新"运算符分配类?
解决方案
我们需要做的就是声明该类的新运算符为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来初始化它?
我不相信你的动机。
有充分的理由在免费商店中创建RAII类。
例如,我有一个RAII锁类。我有一段遍历代码的路径,其中只有在满足某些条件的情况下才需要锁定(它是视频播放器,并且只有在加载并播放视频的情况下,才需要在渲染循环中保持锁定;如果没有加载,我不需要)。因此,在免费存储区(具有scoped_ptr / auto_ptr)上创建锁的功能非常有用;它使我可以使用相同的代码路径,而不管是否必须取出锁。
即像这样的东西:
auto_ptr<lock> l; if(needs_lock) { l.reset(new lock(mtx)); } render();
如果我只能在堆栈上创建锁,那么我将无法做到这一点。
@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();
在我的特定情况下,如果不需要锁定,则互斥体甚至不存在,因此我认为这种方法将更难使用。
我想我真正要了解的是禁止在免费商店中创建这些对象的理由。